2010-07-25 3 views
9

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

и как использовать его, как это:


$comments = $this->em->getRepository('comments')->findAll(); 
foreach($comments as $comment){ 
    foreach($comment->getKeywords() as $keyword){ 
     $keyword->getText(); 
    } 
}

и получил эти ошибки:

 
Notice: Undefined index: comment_id in C:\web_includes\doctrine\ORM\Persisters\BasicEntityPersister.php on line 1096 
Notice: Trying to get property of non-object in C:\web_includes\doctrine\ORM\Persisters\BasicEntityPersister.php on line 1098 
Warning: Invalid argument supplied for foreach() in C:\web_includes\doctrine\ORM\Persisters\BasicEntityPersister.php on line 1098 
Notice: Undefined index: comment_id in C:\web_includes\doctrine\ORM\PersistentCollection.php on line 168 
Fatal error: Call to a member function setValue() on a non-object in C:\web_includes\doctrine\ORM\PersistentCollection.php on line 169 
Что не так? где следует определять comment_id? Верно ли мое отображение? я действительно застрял и нуждаюсь в помощи, поэтому, пожалуйста, любые советы очень приветствуются.

+0

, что о 'comment_id'? как вы устанавливаете отношения betn comments и ключевые слова? – Sadat

+0

comment_id - это поле в базе данных в таблице ключевых слов, в которой есть идентификатор комментария, к которому относится это ключевое слово. Я полагаю, что доктрина будет использовать его при выборе ключевых слов для комментариев. Отношение такое же OneToMany (targetEntity = "keywords", mappedBy = "comment_id") Правильно ли это? – SET

ответ

13

Атрибут 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;} 
} 

Использование схемы 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. Смотрите также документацию о том, как Обратные/Владельцам работ:

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

+0

ЭТО ДЕЙСТВИТЕЛЬНО РАБОТАЕТ! Большое спасибо. Но я должен спросить, в чем разница между однонаправленными отношениями и двунаправленностью.Кроме того, какая сущность в моем случае будет обратной и что будет владеть. Я полагаю, что комментарий в владении и keywodrs является обратным, но не могу сказать, почему. – SET

+0

Ключевые слова являются собственностью, поскольку внешний ключ «comment_id» находится в таблице ключевых слов. Однонаправленное означает, что вы можете только перейти от комментария к ключевым словам, используя Комментарий :: getKeywords(). Двунаправленный означает, что вы можете идти в обоих направлениях с дополнительным ключом :: getComment() (отсутствует в моем примере). Глава ассоциации довольно длинна, но вы должны прочитать главы «Работа с ассоциациями» и «Сопоставление ассоциаций», чтобы получить всю концепцию. – beberlei

Смежные вопросы