Symfony2: ManyToMany relation and Collection form type

doctrine-orm, symfony

Solution

Well, I don't deal much with doctrine, but seems that you are inserting a tag with the same ID/Name in the same collection. I think you could check the tag existence before insert

public function existTags(\Doctrine\Common\Collections\ArrayCollection $tags)
{
    foreach($this->tags as $tag)
    {
        if ( $tag->getID() === $tags->getId() )
            return true;
    }
    return false;
}

And then

public function addTag(\My\BlogBundle\Entity\Tag $tags)
{
    if ( !$this->existTag($tags) );
        $this->tags[] = $tags;
}

These are my models:

namespace models;


/**
 * @Entity
 * @Table(name="tag")
 */
class Tag
{

    /**
     * @Id @Column(type="integer", nullable=false, name="id")
     * @GeneratedValue(strategy="AUTO")
     */
    protected $id;


    /**
     * @Column(type="string", nullable=false)
     */
    protected $name;

    public function getId(){ return $this->id; }
    public function getName(){ return $this->name; }

    public function setId($id){ $this->id = $id; }
    public function setName($name){ $this->name = $name; }


}

The blog entry:

namespace models;

use \Doctrine\Common\Collections\ArrayCollection;

/**
 * @Entity
 * @Table(name="entry")
 */
class Entry
{

    /**
     * @Id @Column(type="integer", nullable=false, name="id")
     * @GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @Column(type="string", nullable=false, name="body")
     */
    protected $body;



    /**
     * @ManyToMany(targetEntity="Tag")
     * @JoinTable(name="entry_tagged",
     *      joinColumns={@JoinColumn(name="entry_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="tag_id", referencedColumnName="id")}
     *      )
     */
    private $tags;





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

    public function existTag(models\Tag $tag)
    {
        foreach($this->tags as $temp)
        {
            if ( $tag->getID() === $temp->getId() )
                return true;
        }
        return false;
    }

    public function addTag(models\Tag $tag)
    {
        if ( !$this->existTag($tag) );
            $this->tags->add($tag);
    }


    public function getId(){ return $this->id; }
    public function getBody(){ return $this->body; }
    public function getTags(){ return $this->tags; }

    public function setId($id){ $this->id = $id; }
    public function setBody($body){ $this->body = $body; }
    public function setTags($tags){ $this->tags = $tags; }

}

Finally, the join table used is "entry_tagged" and looks like this:

entry_id | tag_id

Problem

I'm facing big issue with Collection form type for ManyToMany relation in my Symfony2 project. Environment: - Symfony 2.0.14 - Doctrine 2.1 Here's some code: Post entity ``` class Post { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="string", length=255, nullable=false) */ private $title; /** * @ORM\ManyToMany(targetEntity="Tag", inversedBy="posts", cascade={"persist"}) * @ORM\JoinTable(name="posts_tags") */ private $tags; public function setTags(\Doctrine\Common\Collections\ArrayCollection $tags) { foreach($tags as $tag) { $tag->addSnippet($this); } } public function addTag(\My\BlogBundle\Entity\Tag $tags) { $this->tags[] = $tags; } public function getTags() { return $this->tags; } ``` Tag entity ``` class Tag { /** * @var integer $id * * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string $name * * @ORM\Column(type="string", length=100, unique=true, nullable=false) */ private $name; /** * @var Snippet * * @ORM\ManyToMany(targetEntity="Post", mappedBy="tags") */ private $posts; public function addSnippet(\My\BlogBundle\Entity\Post $posts) { $this->posts[] = $posts; } ``` PostType form class ``` ->add('tags', 'collection', array( 'type' => new TagType(), 'allow_add' => true, 'prototype' => true, 'by_reference' => false, )) ``` Everything works perfectly, but it throws an error while inserting a tag that already exists in database `SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'tag1' for key 'UNIQ_6FBC94265E237E06'`. Do you have any workaround for this issue or am I missing something? My controller is a standard CRUD controller generated by `app/console`.`enter code here`

Original source