Я читаю официальную документацию и тонны нитей, но до сих пор не нашел решения для своей ситуации. Мой случай очень прост. У меня есть 2 объекта: комментарии и ключевые слова для них. Один комментарий может содержать много ключевых слов, но каждое ключевое слово – только для одного комментария. Ключевые слова не уникальны в таблице ключевых слов. Поэтому я решил, что это отношение «один ко многим». Структура таблиц проста:
ключевые слова
id int(11) comment_id int(11) text varchar(30)
Комментарии
id int(11) text text
вот как я их сопоставил:
/** * @Entity * @Table(name="comments") **/ class Comments { /** @Id @Column(type="integer") */ private $id; /** @Column(type="text") */ private $text; /** * @OneToMany(targetEntity="keywords", mappedBy="comment_id") */ private $keywords; public function getText(){return $this->text;} public function getId(){return $this->id;} public function getKeywords(){return $this->keywords;} } /** * @Entity * @Table(name="keywords") */ class Keywords { /** @Id @Column(type="integer") */ private $id; private $text; public function getText(){return $this->text;} public function getId(){return $this->id;} }
/** * @Entity * @Table(name="comments") **/ class Comments { /** @Id @Column(type="integer") */ private $id; /** @Column(type="text") */ private $text; /** * @OneToMany(targetEntity="keywords", mappedBy="comment_id") */ private $keywords; public function getText(){return $this->text;} public function getId(){return $this->id;} public function getKeywords(){return $this->keywords;} } /** * @Entity * @Table(name="keywords") */ class Keywords { /** @Id @Column(type="integer") */ private $id; private $text; public function getText(){return $this->text;} public function getId(){return $this->id;} }
и как его использовать:
$comments = $this->em->getRepository('comments' )->findAll(); foreach($comments as $comment){ foreach($comment->getKeywords() as $keyword){ $keyword->getText(); } }
и по$comments = $this->em->getRepository('comments' )->findAll(); foreach($comments as $comment){ foreach($comment->getKeywords() as $keyword){ $keyword->getText(); } }
и получил эти ошибки:
Примечание. Неопределенный индекс: comment_id в C: \ web_includes \ doctrine \ ORM \ Persisters \ BasicEntityPersister.php в строке 1096 Примечание. Попытка получить свойство не-объекта в C: \ web_includes \ doctrine \ ORM \ Persisters \ BasicEntityPersister.php в строке 1098 Предупреждение: неверный аргумент, предоставленный foreach () в C: \ web_includes \ doctrine \ ORM \ Persisters \ BasicEntityPersister.php в строке 1098 Примечание. Неопределенный индекс: comment_id в C: \ web_includes \ doctrine \ ORM \ PersistentCollection.php в строке 168 Неустранимая ошибка: вызов функции-члена setValue () для не-объекта в C: \ web_includes \ doctrine \ ORM \ PersistentCollection.php в строке 169
Что не так? где следует определять comment_id? Верно ли мое отображение? я действительно застрял и нуждаюсь в помощи, поэтому, пожалуйста, любые советы очень приветствуются.
Атрибут mappedBy ничего не говорит о имени внешнего ключа. Это то, что для аннотации «@JoinColumn». Правильное отображение для этого сценария будет:
/** * @Entity * @Table(name="comments") **/ class Comments { /** @Id @Column(type="integer") */ private $id; /** @Column(type="text") */ private $text; /** * @OneToMany(targetEntity="keywords", mappedBy="comment") */ private $keywords; public function getText(){return $this->text;} public function getId(){return $this->id;} public function getKeywords(){return $this->keywords;} } /** * @Entity * @Table(name="keywords") */ class Keywords { /** @Id @Column(type="integer") */ private $id; /** * @ManyToOne(targetEntity="Comments", inversedBy="keywords") */ private $comment; /** * @Column(type="text") */ private $text; public function getText(){return $this->text;} public function getId(){return $this->id;} }
Используя Schema Tool, он генерирует SQL, который равен вашей схеме:
CREATE TABLE comments (id INT NOT NULL, text LONGTEXT NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; CREATE TABLE keywords (id INT NOT NULL, comment_id INT DEFAULT NULL, text LONGTEXT NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; ALTER TABLE keywords ADD FOREIGN KEY (comment_id) REFERENCES comments(id);
Две проблемы в вашем отображении:
Все это звучит очень сложно, но это очень эффективный путь от технической перспективы ORM, потому что он позволяет обновлять ассоциации с наименьшим количеством требуемых операторов SQL UPDATE. См. Документы о том, как работает Inverse / Owning: