Search code examples
phpsymfonydoctrine-ormmany-to-manyfixtures

symfony 2 Fixtures for many to many relationship


How to set up fixtures for symfony 2 in for many to many relationship, Following 2 entities are made by command lines, And then added some lines for many to many relationship

Entity 1: Blog Class

<?php

namespace Acme\MainBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Blog
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Acme\MainBundle\Entity\BlogRepository")
*/
 class Blog {

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @ORM\ManyToMany(targetEntity="tag", inversedBy="blogs")
 * @ORM\JoinTable(name="blog_tag",
 *      joinColumns={@ORM\JoinColumn(name="blog_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}
 *      )
 **/
protected $tags;

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


/**
 * @var string
 *
 * @ORM\Column(name="title", type="string", length=255)
 */
private $title;

/**
 * @var string
 *
 * @ORM\Column(name="subTitle", type="text")
 */
private $subTitle;

/**
 * @var string
 *
 * @ORM\Column(name="author", type="string", length=255)
 */

private $author;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="createdAt", type="datetime")
 */
private $createdAt;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="updatedAt", type="datetime")
 */
private $updatedAt;

/**
 * @var string
 *
 * @ORM\Column(name="content", type="text")
 */
private $content;

/**
 * @var boolean
 *
 * @ORM\Column(name="isPublished", type="boolean")
 */
private $isPublished;

/**
 * Get id
 *
 * @return integer 
 */
public function getId() {
    return $this->id;
}

/**
 * Set title
 *
 * @param string $title
 * @return Blog
 */
public function setTitle($title) {
    $this->title = $title;

    return $this;
}

/**
 * Get title
 *
 * @return string 
 */
public function getTitle() {
    return $this->title;
}

/**
 * Set author
 *
 * @param string $author
 * @return Blog
 */
public function setAuthor($author) {
    $this->author = $author;

    return $this;
}

/**
 * Get author
 *
 * @return string 
 */
public function getAuthor() {
    return $this->author;
}

/**
 * Set createdAt
 *
 * @param \DateTime $createdAt
 * @return Blog
 */
public function setCreatedAt($createdAt) {
    $this->createdAt = $createdAt;

    return $this;
}

/**
 * Get createdAt
 *
 * @return \DateTime 
 */
public function getCreatedAt() {
    return $this->createdAt;
}

/**
 * Set updatedAt
 *
 * @param \DateTime $updatedAt
 * @return Blog
 */
public function setUpdatedAt($updatedAt) {
    $this->updatedAt = $updatedAt;

    return $this;
}

/**
 * Get updatedAt
 *
 * @return \DateTime 
 */
public function getUpdatedAt() {
    return $this->updatedAt;
}

/**
 * Set content
 *
 * @param string $content
 * @return Blog
 */
public function setContent($content) {
    $this->content = $content;

    return $this;
}

/**
 * Get content
 *
 * @return string 
 */
public function getContent() {
    return $this->content;
}

/**
 * Set isPublished
 *
 * @param boolean $isPublished
 * @return Blog
 */
public function setIsPublished($isPublished) {
    $this->isPublished = $isPublished;

    return $this;
}

/**
 * Get isPublished
 *
 * @return boolean 
 */
public function getIsPublished() {
    return $this->isPublished;
}

public function __toString() {
    return strval($this->id);
}


/**
 * Set subTitle
 *
 * @param string $subTitle
 * @return Blog
 */
public function setSubTitle($subTitle)
{
    $this->subTitle = $subTitle;

    return $this;
}

/**
 * Get subTitle
 *
 * @return string 
 */
public function getSubTitle()
{
    return $this->subTitle;
}

/**
 * Add tags
 *
 * @param \Acme\MainBundle\Entity\tag $tags
 * @return Blog
 */
public function addTag(\Acme\MainBundle\Entity\tag $tags)
{
    $this->tags[] = $tags;
    $tags->addBlog($this);

    return $this;
}

/**
 * Remove tags
 *
 * @param \Acme\MainBundle\Entity\tag $tags
 */
public function removeTag(\Acme\MainBundle\Entity\tag $tags)
{
    $this->tags->removeElement($tags);
}

/**
 * Get tags
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getTags()
{
    return $this->tags;
}
}

Entity 2: Tag Class

<?php

namespace Acme\MainBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Tag
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Acme\MainBundle\Entity\TagRepository")
 */
class Tag {

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @ORM\ManyToMany(targetEntity="blog", mappedBy="tags")
 **/

protected $blogs;

/**
 * @var string
 *
 * @ORM\Column(name="tag", type="string", length=255)
 */
private $tag;

/**
 * @var boolean
 *
 * @ORM\Column(name="isPublished", type="boolean")
 */
private $isPublished;

/**
 * Get id
 *
 * @return integer 
 */
public function getId() {
    return $this->id;
}

/**
 * Set tag
 *
 * @param string $tag
 * @return Tag
 */
public function setTag($tag) {
    $this->tag = $tag;

    return $this;
}

/**
 * Get tag
 *
 * @return string 
 */
public function getTag() {
    return $this->tag;
}

/**
 * Set isPublished
 *
 * @param boolean $isPublished
 * @return Tag
 */
public function setIsPublished($isPublished) {
    $this->isPublished = $isPublished;

    return $this;
}

/**
 * Get isPublished
 *
 * @return boolean 
 */
public function getIsPublished() {
    return $this->isPublished;
}

public function __toString() {
    return strval($this->id);
}

/**
 * Constructor
 */
public function __construct()
{
    $this->blogs = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add blogs
 *
 * @param \Acme\MainBundle\Entity\blog $blogs
 * @return Tag
 */
public function addBlog(\Acme\MainBundle\Entity\blog $blogs)
{
    $this->blogs[] = $blogs;
    $blogs->addTag($this);


    return $this;
}

/**
 * Remove blogs
 *
 * @param \Acme\MainBundle\Entity\blog $blogs
 */
public function removeBlog(\Acme\MainBundle\Entity\blog $blogs)
{
    $this->blogs->removeElement($blogs);
}

/**
 * Get blogs
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getBlogs()
{
    return $this->blogs;
}
}

Solution

  • Attention!!!

    You have a circular reference in your code!!! When you add a tag to a blog, it call add blog to tag and so on, please fix it in like this:

    Blog

    /**
     * Add tags
     *
     * @param \Acme\MainBundle\Entity\tag $tags
     * @return Blog
     */
    public function addTag(\Acme\MainBundle\Entity\tag $tags)
    {
        if (!$this->tags->contains($tags))
        {
            $this->tags[] = $tags;
            $tags->addBlog($this);
        }
    
        return $this;
    }
    

    Tag

    /**
     * Add blogs
     *
     * @param \Acme\MainBundle\Entity\blog $blogs
     * @return Tag
     */
    public function addBlog(\Acme\MainBundle\Entity\blog $blogs)
    {
        if (!$this->blogs->contains($blogs))
        {
            $this->blogs[] = $blogs;
            $blogs->addTag($this);
        }
    
    
        return $this;
    }
    

    For your question:

    First, install and configure the DoctrineFixturesBundle. Use the ordered fixture features to load first the tag then the blog.

    Then I write for you this example fixtures:

    TagFixtures

    <?php
    
    namespace Acme\MainBundle\DataFixtures\ORM;
    
    use Acme\MainBundle Bundle\Entity\Tag;
    use Doctrine\Common\DataFixtures\AbstractFixture;
    use Doctrine\Common\Persistence\ObjectManager;
    use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
    
    class TagFixtures  extends AbstractFixture implements OrderedFixtureInterface {
    
        /**
         * Load data fixtures with the passed EntityManager
         *
         * @param \Doctrine\Common\Persistence\ObjectManager $manager
         */
        function load(ObjectManager $manager)
        {
            $tag1 = new Tag();
            $tag1->setTag("tag name 1");
            $tag1->setIsPublished(true);
    
            $tag2 = new Tag();
            $tag2->setTag("tag name 2");
            $tag2->setIsPublished(true);
    
            $manager->persist($tag1);
            $manager->persist($tag2);
            $this->addReference('tag-tag_1', $tag1);
            $this->addReference('tag-tag_2', $tag2);
    
            $manager->flush();
    
        }
    
        /**
         * Get the order of this fixture
         *
         * @return integer
         */
        function getOrder()
        {
            return 1;
        }
    }
    

    BlogFixtures

    <?php
    
    namespace Acme\MainBundle\DataFixtures\ORM;
    
    use Acme\MainBundle\Entity\Blog;
    use Doctrine\Common\DataFixtures\AbstractFixture;
    use Doctrine\Common\Persistence\ObjectManager;
    use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
    
    class BlogFixtures  extends AbstractFixture implements OrderedFixtureInterface {
    
        /**
         * Load data fixtures with the passed EntityManager
         *
         * @param \Doctrine\Common\Persistence\ObjectManager $manager
         */
        function load(ObjectManager $manager)
        {
    
            $blog = new Blog();
            $blog->setTitle('Happy new year');
            $blog->setAuthor("me");
            $blog->setIsPublished(true);
            $blog->setContent("Happy new year");
            $blog->setSubTitle("2015");
            $blog->setCreatedAt(new \DateTime('now'));
            $blog->setUpdatedAt(new \DateTime('now'));
    
            $blog->addTag($this->getReference('tag-tag_1'));
    //        $blog->addTag($this->getReference('tag-tag_2'));
    
            $manager->persist($blog);
    //        $this->addReference('blog-blog_1', $blog);
    
            $manager->flush();
    
        }
    
        /**
         * Get the order of this fixture
         *
         * @return integer
         */
        function getOrder()
        {
            return 2;
        }
    }
    

    Hope this help and happy new year!