0

基本上,我有两个表(文章和标签),我想用一些额外的属性建立多对多(一篇文章可以有很多标签,一个标签可以分配给很多文章)关系。我可以在 Doctrine2 中通过将其分解为两个单独的关系(一对多、多对一)和一个带有我的额外属性的关系表 ArticleTag 来编写它。

我的问题是我不知道我是否可以让 Doctrine2 也为我创建连接表实体。我的意思是当我打电话时:

$article = /* create new article, etc... */
$tag = /* create new tag, etc... */
$article->addTag($tag);

$em->persist($article);
$em->flush();

确实在数据库中创建了文章和标签实体,但它创建文章标签实体(换句话说,它不创建文章和标签之间的连接)。我可以自己创建它,但我宁愿依靠 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;

}
4

2 回答 2

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 眼中的一个类代表一个实体源,该类的每个实例都代表一个实体。在简单的多对多表中,多对多表不是实体。ArticleTag实际上,它只是两个实体之间的关系,这就是为什么 Doctrine 允许您绕过此逻辑并且如果实体只有外键则不需要实体。

但是,一旦您向该表添加其他元数据,它就不再是关系表。我已经与许多看法不同的人讨论过这个问题,但事实并非如此。是的,它定义实体 1 和实体 2 是相关的,但附加列定义了关联所需的附加元数据。因此,它本身就是一个实体,必须如此反映。

我已经为此苦苦挣扎了很长一段时间,直到我最终添加了上面显示的代码。

于 2013-01-09T18:18:05.420 回答
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;  }
于 2013-01-09T17:08:03.357 回答