基本上,我有两个表(文章和标签),我想要多对多(一篇文章可以有很多标签,一个标签可以分配给许多文章)与一些额外属性的关系。 我可以在Doctrine2中将它写成两个独立的关系(一对多,多对一)和一个关系表ArticleTag与我的额外属性。
我的问题是我不知道是否可以让Doctrine2为我创建连接表实体。我的意思是当我打电话时:
$article = /* create new article, etc... */
$tag = /* create new tag, etc... */
$article->addTag($tag);
$em->persist($article);
$em->flush();
DOES 在数据库中同时创建Article和Tag实体,但不会创建ArticleTag实体(换句话说,它不会创建Article和标签)。我可以自己创造它,但我宁愿依赖Doctrine2 当然,当我使用Doctrine2生成的标准连接表时,它工作正常,但我需要这些额外的属性。
有没有人有任何想法,或者我真的必须手动完成吗?
编辑:源代码
/**
* @ORM\Entity
*/
class Article {
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
protected $id;
/**
* @ORM\OneToMany(targetEntity="Tag", mappedBy="article", cascade={"persist"})
* @ORM\JoinTable(name="ArticleTag", joinColumns={@ORM\JoinColumn(name="article_id", referencedColumnName="id")})
* )
*/
protected $tags;
...
}
/**
* @ORM\Entity
*/
class ArticleTag {
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="Article")
*/
private $article;
/**
* @ORM\ManyToOne(targetEntity="Tag")
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id")
*/
private $tag;
/**
* @ORM\Column(type="float")
*/
protected $priority = 0.5;
}
/**
* @ORM\Entity
*/
class Tag {
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
protected $id;
/**
* @ORM\Column(type="string", length=32)
*/
protected $name;
}
答案 0 :(得分:2)
本身没有办法自动执行此操作,但您可以将addTag
类上的Article
方法更改为以下内容:
public function addTag(Tag $tag, $priority)
{
$articleTag = new ArticleTag();
$articleTag->setTag($tag);
$articleTag->setArticle($this);
$articleTag->setPriority($priority);
$this->addArticleTag($articleTag);
return $this;
}
这样,您可以集中代码并隐藏ArticleTag
条目的创建。有关其他解释,请参阅此逻辑背后的原因:
Doctrine眼中的一个类代表一个实体源,该类的每个实例代表一个实体。在简单的多对多表中,多对多表不是实体。实际上,它只是两个实体之间的关系,这就是为什么Doctrine允许你绕过这个逻辑,如果它只有外键就不需要ArticleTag
实体。
但是,一旦向该表添加其他元数据,它就不再是关系表。我和很多看过不同东西的人讨论过这个问题,但事实并非如此。是的,它定义实体1和实体2是相关的,但该附加列定义了关联所需的其他元数据。因此,它本身就是一个实体,必须如此反映。
我一直在努力解决这段问题,直到最后我添加了上面显示的代码。
答案 1 :(得分:0)
我的实体可以在没有任何加入实体的情况下使用其标签(我的架构中的主题)加入文章,您是否因任何特定原因需要加入实体?
使用
$article->getSubjects()->add($subject);
实体
/**
* @ORM\Entity(repositoryClass="\Fam\Article")
* @ORM\Table(name="Article")
*/
class Article{
/*StartProtected*/
protected $links = array();
public function __construct()
{
$this->subjects = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* @ORM\ManyToMany(targetEntity="Subject")
* @ORM\JoinTable(name="Article_to_Subject",
* joinColumns={@ORM\JoinColumn(name="articleId", referencedColumnName="articleId")},
* inverseJoinColumns={@ORM\JoinColumn(name="subjectId", referencedColumnName="subjectId")}
* )
*/
protected $subjects;
/**
*
* @return \Doctrine\Common\Collections\ArrayCollection
*/
public function getSubjects()
{
return $this->subjects;
}
public function removeSubjects(){ $this->subjects = new \Doctrine\Common\Collections\ArrayCollection(); return $this; }