在更新时将唯一身份插入链接表

时间:2013-01-25 00:19:05

标签: symfony doctrine-orm

我有一个场景,我正在更新一个博客帖子,该帖子通过多对多关系(在名为blog_link_tags的链接表中)为其分配了多个标签,如下所示:

...

$em = $this->getDoctrine()->getManager();
$blogPost = $em->getRepository('MyBlogBundle:Blog')->find($postId);


$blogPost
    ->setTitle( $request->request->get('post_title', '') )
    ->setBody( $request->request->get('post_body', '') )
    ->setLive(true);


$postTags = json_decode( $request->request->get('post_tags', '') );
$tagRepository = $em->getRepository('MyBlogBundle:BlogTag');

foreach($postTags as $postTag) {
    $tag = $tagRepository->find( $postTag->id );
    if (!$tag) {
        throw $this->createNotFoundException('Tag not found: ' . $tag->title);
    }
    $blogPost->addTag($tag);
}

$em->flush();

....

正如您可能知道的那样,如果我编辑博客文章并添加新标签,那么它将创建重复记录。

截断当前博客帖子ID的blog_link_tag记录表的最佳方法是什么,或者只插入那些唯一的标记ID?它是否会在foreach循环中的以下行中执行:

$tag = $tagRepository->find( $postTag->id );

但请检查标签是否存在以及链接表中是否存在?或者Doctrine 2是否提供了更好的方法来实现这样的行动?

2 个答案:

答案 0 :(得分:2)

假设$blogPost是拥有方,您有2个解决方案:

首先,在$blogPost->getTags()->clear()之前使用foreach。小心这一点,它将删除blog_link_tags中的所有链接标签。但是如果你再次在你的foreach中添加它们就可以了。取决于内容$postTags

第二个是在if(!$blogPost->getTags()->contains($tag))

之前测试$blogPost->addTag($tag);

请记住,您正在many-to-many关系中处理ArrayCollection

NB: 我觉得你这里有一个错字:

 if (!$tag) {
        throw $this->createNotFoundException('Tag not found: ' . $tag->title);
    }

如果$tag未退出,则无法使用$tag->title。我想你想用$postTag->title

答案 1 :(得分:1)

就我而言,我首先会为Post实体创建一个 FormType ,这样我就不必在控制器中编写任何凌乱代码了。一切都是自动化,清洁和安全的。

接下来,我将在Post实体中管理标签,如下所示:

class Post
{

    private $tags;

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

    public function setTags($tags)
    {
        $this->tags->clear();

        foreach ($tags as $tag) {
            $this->addTag($tag);
        }

        return $this;
    }

    public function addTag(Tag $tag)
    {
         if (!$this->tags->contains($tag)) {
             $this->tags[] = $tag;
         }
    }
}