2010-07-25 71 views
9

我阅读官方文档和大量的线程,但仍然没有找到我的情况的解决方案。我的情况非常基本。我有两个实体:评论和关键字。一个评论可以有许多关键字,但每个关键字只能用于一个评论。关键字表中的关键字不是唯一的。所以我决定这是一对多的关系。表结构只是想如下:理解学说中关系映射的问题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评论和关键字? – Sadat 2010-07-25 10:38:59

+0

comment_id是关键字表中数据库中具有此关键字所属注释ID的字段。我想教条会在选择关键字时使用它。 关系是这样的 OneToMany(targetEntity =“keywords”,mappedBy =“comment_id”) 是不是正确? – SET 2010-07-25 11:03:22

回答

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;} 
} 

使用Schema工具它产生相当于您的模式的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. 你必须了解拥有和反面的区别。只有一对多单向关系需要第三个连接表。然而像双向关系一样,在我拥有的side属性Keyword :: $ comment的映射中,它是有效的。
  2. “mappedBy”指的是另一个targetEntity上属于“此关联的另一方”的属性。 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 2010-07-25 23:31:50

+0

关键字是拥有方,因为外键“comment_id”在关键字表上。 单向意味着您只能使用Comment :: getKeywords()从Comment评论到关键字。双向意味着你可以在两个方向上使用额外的Keyword :: getComment()(在我的例子中缺少)。 协会章节比较冗长,但您应该阅读“协同工作”和“协会映射”章节以获取整个概念。 – beberlei 2010-07-26 11:55:29