Symfony 2:ManyToMany关系和唯一对象

时间:2013-01-05 22:25:11

标签: symfony doctrine doctrine-orm

我正在学习SF2 - 对完成的工作印象深刻,面对我无法解决的第一个真正的问题。

我有两个实体:Post和Tag。缩短代码如下:

class Tag
{
    /**
     * @ORM\ManyToMany(targetEntity="Post", mappedBy="tags", cascade={"persist"})
     */
    private $posts;

    public function __construct()
    {
        $this->posts = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * @param \My\AppBundle\Entity\Snippet $posts
     * @return Tag
     */
    public function addSnippet(\My\AppBundle\Entity\Post $posts)
    {
        $this->posts[] = $posts;

        return $this;
    }

    /**
     * @param \My\AppBundle\Entity\Snippet $snippets
     */
    public function removeSnippet(\My\AppBundle\Entity\Post $posts)
    {
        $this->posts->removeElement($posts);
    }

    /**
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getSnippets()
    {
        return $this->posts;
    }
}

class Post
{
    /**
     * @ORM\ManyToMany(targetEntity="Tag", inversedBy="posts", cascade={"persist"})
     * @ORM\JoinTable(name="posts_tags",
     *     joinColumns={@ORM\JoinColumn(name="post_id", referencedColumnName="id", unique=true, onDelete="cascade")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id", unique=true, onDelete="cascade")}
     * )
     */
    private $tags;

    public function __construct()
    {
        $this->tags = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * @param \My\AppBundle\Entity\Tag $tags
     * @return Snippet
     */
    public function addTag(\My\AppBundle\Entity\Tag $tags)
    {
        $this->tags[] = $tags;

        return $this;
    }

    /**
     * @param \My\AppBundle\Entity\Tag $tags
     */
    public function removeTag(\My\AppBundle\Entity\Tag $tags)
    {
        $this->tags->removeElement($tags);
    }

    /**
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getTags()
    {
        return $this->tags;
    }
}

如您所见,我在两个实体之间有M:M关系。

我还有一个表格,用于添加带有嵌入式标签集合的帖子:

        $builder
            ->add('title')
            ->add('tags', 'collection', array(
                'type' => new \My\AppBundle\Form\TagType(),
                'allow_add' => true,
                'by_reference' => false,
                'prototype' => true
            ))
        ;

TagType表单类:

$builder->add('name');

一切都按预期工作。除了一件事:如果有一个具有以下名称的Tag对象,我将得到SQLSTATE[23000]: Integrity constraint violation MySQL错误,这是显而易见的。如果我应用唯一的验证约束,我可以添加一个标签发布(如果它已经存在于数据库中)。

很明显,我需要检查数据库中是否存在以下标记,并且仅在不存在时添加它,但是......如何以Symfony的方式进行添加?

任何建议都赞赏!

1 个答案:

答案 0 :(得分:1)

您可以使用UniqueEntity来处理此问题。我无法在您的标签类或您的“名称”声明中看到您的注释,但如果您添加类似下面的内容,它应该根据名称为您提供一个唯一的验证约束,并附带可选的消息。

/**
 * @ORM\Entity
 * @UniqueEntity(fields="name", message="This tag name already exists")
 */
class Tag...

/**
 * @var string $name
 *
 * @ORM\Column(name="name", type="string", length=255, unique=true)
 */
protected $name;