Doctrine: insert related object (tag) if not exists in db

时间:2016-08-31 12:30:31

标签: symfony orm doctrine

I'm creating a simple blog post systems. I just have 2 entities News and Tag.

I created a "manyToMany" relation between News and Tag.

Doctrine created a third table (called news_tag) in my database to map the relation between my news and my tag like this one:

+------+----------+------+
|  ID  |  news_id |tag_id|  
+------+----------+------+
|  1   |  1       |  1   | 
|  2   |  1       |  2   | 
|  3   |  2       |  3   | 
|  4   |  2       |  2   | 
+------+----------+------+

The relation works fine when I add a news in my db. The tag are mapped to the news automatically

My problem is: The field 'name' of my tag table is unique. Which is normal I think.

Ok let's say I'm adding 2 news both having the same tag 'november' . . . I will get a violation of unique key constraint !

I thought Dotrine was able to understand in this case it should not try to insert a duplicated tag in my tag table.

I would like in this case doctrine would map only the relation of the duplicated tag (by inserting relation in my table called news_tag) without inserting the tag into the table called 'tag' (which will obviously throw a violation of unique key constraint)

Can you help me to solve that problem ?

Edit here is the code of my controller to add a news:

   public function insertNewsAction(Request $request)
    {
        try{
        $em = $this->getDoctrine()->getManager();
        $news = new News();

        $formNews = $this->createForm(NewsType::class, $news);
        $formNews->handleRequest($request);
        $postedDatas = $formNews->getData();

        /* handling of tags field  */      
        $tagsTemp = $postedDatas->getTags();
        $tags = explode(';', $tagsTemp);

        // convert textfield  of my form to ArrayCollection 
        $news->setTags(new ArrayCollection);

        foreach($tags as $singleTag)
        {
            $tag = new Tag();
            $tag->setName($singleTag);
            $news->addTag($tag);
        }

        $em->persist($news);
        $em->flush();
        $this->addFlash('notice', 'News is correctly inserted');

        return $this->render('MyBundle:Form:news.html.twig');
        } catch (Exception $ex) {
            $this->addFlash('error', 'Flush error. Error news1');
            $this->render('MyBundle:Form:news.html.twig');
        }
    }

1 个答案:

答案 0 :(得分:1)

您遇到的问题是您要为每个帖子创建新的Tag个实体,因此Doctrine会尝试保留它们,然后数据库会抱怨您的独特限制。

您的插入代码应类似于:

$news = //get the NEWS to persist
foreach($tags as $tag)
{
    if (($persistedTag = $entityManager->getRepository('AppBundle:Tag')->findOneByName($tag))==null)
    {
        $persistedTag = new Tag();
        //Fill the new Tag entity
        $entityManager->persist($persistedTag);
    }
    $persistedTag->addNews($news);
    $news->addTag($persistedTag);
}
$entityManager->flush();