проблема понимания отношения отображения в доктрине 2

Я читаю официальную документацию и тонны нитей, но до сих пор не нашел решения для своей ситуации. Мой случай очень прост. У меня есть 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); 

Две проблемы в вашем отображении:

  1. Вы должны понимать разницу между владением и обратной стороной. Просто одностороннее однонаправленное отношение требует третьей таблицы соединений. Однако с двунаправленным отношением, подобным моему сопоставлению с собственностью, свойство Keyword :: $ comment работает.
  2. «mappedBy» относится к свойству на другой targetEntity, которая является «другой стороной этих ассоциаций». InversedBy имеет то же значение, что и inversedBy всегда указывается на стороне владельца, отображаемой на обратной стороне.

Все это звучит очень сложно, но это очень эффективный путь от технической перспективы ORM, потому что он позволяет обновлять ассоциации с наименьшим количеством требуемых операторов SQL UPDATE. См. Документы о том, как работает Inverse / Owning:

http://www.doctrine-project.org/projects/orm/2.0/docs/reference/association-mapping/en#owning-side-and-inverse-side