1 Вопрос: понимание проблем соотношения в доктрине 2

вопрос создан в Sun, Jan 23, 2011 12:00 AM

Я читаю официальную документацию и массу тем, но все еще не могу найти решение для моей ситуации. Мой случай очень прост. У меня есть 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? Правильно ли мое отображение? Я действительно застрял и нуждаюсь в помощи, поэтому, пожалуйста, любые советы очень приветствуются.

    
9
  1. как насчет comment_id? как установить отношение между комментариями и ключевыми словами?
    2010-07-25 10: 38: 59Z
  2. comment_id - это поле в базе данных в таблице ключевых слов с идентификатором комментария, к которому принадлежит это ключевое слово. Я полагаю, доктрина будет использовать его при выборе ключевых слов для комментариев. отношение похоже на это OneToMany (targetEntity = "Keywords", mappedBy = "comment_id") это правильно?
    2010-07-25 11: 03: 22Z
1 ответ                              1                         

Атрибут 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. Вы должны понимать разницу между владением и обратной стороной. Простое однонаправленное отношение «один ко многим» требует третьей таблицы соединений. Однако с двунаправленным отношением, как в моем отображении со свойством sideing Keyword :: $comment, это работает.
  2. «mappedBy» относится к свойству другого targetEntity, которое является «другой стороной этой ассоциации». InversedBy имеет примерно то же значение, только что inversedBy всегда указывается на стороне владельца, mappedBy на обратной стороне.

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

13

2010-07-25 18: 23: 15Z
  1. ЭТО ДЕЙСТВИТЕЛЬНО РАБОТАЕТ! Большое спасибо. Но я должен спросить, в чем разница между однонаправленными отношениями и двунаправленными. Кроме того, какая сущность в моем случае будет обратной стороной и чем будет владеть. Я полагаю, что комментарии о владельце и keywodrs обратные, но не могу сказать, почему.
    2010-07-25 23: 31: 50Z
  2. Ключевые слова являются собственниками, поскольку внешний ключ "comment_id" находится в таблице ключевых слов. Однонаправленный означает, что вы можете переходить только от комментариев к ключевым словам, используя Comment :: getKeywords (). Двунаправленный означает, что вы можете идти в обоих направлениях с помощью дополнительного Keyword :: getComment () (отсутствует в моем примере). Глава об ассоциации довольно длинная, но вы должны прочитать главы «Работа с ассоциациями» и «Сопоставления ассоциаций», чтобы получить полную концепцию.
    2010-07-26 11: 55: 29Z
источник размещен Вот