0

我有一个场景,我正在更新一篇博文,该博文通过多对多关系(在名为 的链接表中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();

....

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

截断blog_link_tag当前博客文章 ID 的记录表或仅插入那些唯一的标签 ID 的最佳方法是什么?是否会在 foreach 循环中的以下行中执行此操作:

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

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

4

2 回答 2

2

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

第一个解决方案,$blogPost->getTags()->clear()foreach. 小心这个,它将删除blog_link_tags. 但是,如果您在 foreach 中再次添加它们就可以了。视内容而定$postTags

第二个是测试if(!$blogPost->getTags()->contains($tag))$blogPost->addTag($tag);

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

注意: 我认为你这里有一个错字:

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

如果$tag不退出,则不能使用$tag->title. 我想你想用$postTag->title

于 2013-01-25T08:45:47.260 回答
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;
         }
    }
}
于 2013-01-25T14:06:39.317 回答