我有一个场景,我正在更新一个博客帖子,该帖子通过多对多关系(在名为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是否提供了更好的方法来实现这样的行动?
答案 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;
}
}
}