Creating symfony fixtures are a great way to setup your development or testing environments in your project. In some situations we need to have some demo data in our database in order to test our applications properly. This is the moment when fixtures should be used. Fixtures used to load data to database programatically. And once setted up, they can be easily reused everytime you need them.

Fixtures in Symfony are provided by default and they are a part of Doctrine library, bundled in DoctrineFixturesBundle. If somewhy you don’t have this bundle already, you can simply install it with composer, running this command:

composer require –dev doctrine/doctrine-fixtures-bundle

Creating Symfony Fixtures Class

Let’s say our application needs some demo data for Book and Shelf entities, which would have relationship one-to-many from Shelf entity and many-to-one from Book entity. So let’s create our entities:

<?php

// Book entity

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 */
class Book
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Shelf", inversedBy="books")
     * @ORM\JoinColumn(nullable=false)
     */
    private $shelf;

    /**
     * @ORM\Column(type="string")
     */
    private $title;

    /**
     * @ORM\Column(type="string", name="author_name")
     */
    private $authorName;

    /**
     * @ORM\Column(type="datetime", name="published_at")
     * @Assert\DateTime()
     */
    private $publishedAt;

    // Setters and Getters...
<?php

// Shelf entity

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 */
class Shelf
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="Book", mappedBy="shelf")
     * @ORM\JoinColumn(nullable=false)
     */
    private $books;

    /**
     * @ORM\Column(type="string")
     */
    private $color;

    /**
     * @ORM\Column(type="decimal", precision=10, scale=2)
     */
    private $height;

    /**
     * @ORM\Column(type="decimal", precision=10, scale=2)
     */
    private $width;

    // Setters and Getters...

So that we have our entities for testing, let’s create fixtures:

<?php

// Book fixture

namespace AppBundle\DataFixtures\ORM;

use AppBundle\Entity\Book;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

class LoadBookData extends AbstractFixture
{
    /**
     * {@inheritdoc}
     */
    public function load(ObjectManager $manager)
    {
        $book1 = new Book();
        $book1->setTitle('Harry Potter and the Order of the Phoenix');
        $book1->setAuthorName('J.K. Rowling');
        $book1->setPublishedAt(new \DateTime('2003-06-21'));

        $manager->persist($book1);

        $book2 = new Book();
        $book2->setTitle('The Hunger Games');
        $book2->setAuthorName('Suzanne Collins');
        $book2->setPublishedAt(new \DateTime('2008-09-14'));

        $manager->persist($book2);

        $book3 = new Book();
        $book3->setTitle('To Kill a Mockingbird');
        $book3->setAuthorName('Harper Lee');
        $book3->setPublishedAt(new \DateTime('2006-05-23'));

        $manager->persist($book3);

        $manager->flush();
    }
}
<?php

// Shelf fixture

namespace AppBundle\DataFixtures\ORM;

use AppBundle\Entity\Book;
use AppBundle\Entity\Shelf;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

class LoadShelfData extends AbstractFixture
{
    /**
     * {@inheritdoc}
     */
    public function load(ObjectManager $manager)
    {
        $shelf = new Shelf();
        $shelf->setColor('oak brown');
        $shelf->setHeight('165.50');
        $shelf->setWidth('56.20');

        $manager->persist($shelf);

        $manager->flush();
    }
}

Fixtures should lie in *Bundle/DataFixtures/ORM catalog, this is a default path in symfony. Now that we setted up fixtures, to load them we need run a console command:

php app/console doctrine:fixtures:load

Creating symfony fixtures

If no red lines appear, then congratulations! You have loaded fixtures and now the data can be seen in database.

Setting Relationships And Fixture Order

We have setted up simple fixture. But often you will find that just creating and persisting new entities will be not enough. For example, we need to set up relationships between entities in different fixture classes. Let’s update our fixtures to use relationship and properly order loading of fixtures:

<?php

// Shelf fixture

...

class LoadShelfData extends AbstractFixture implements OrderedFixtureInterface
{
    /**
     * {@inheritdoc}
     */
    public function load(ObjectManager $manager)
    {
        Creating shelf objects...

        $manager->persist($shelf);

        $manager->flush();

        $this->setReference('shelf', $shelf);
    }

    public function getOrder()
    {
        return 1;
    }
}
<?php

// Book fixture

...

class LoadBookData extends AbstractFixture implements OrderedFixtureInterface
{
    /**
     * {@inheritdoc}
     */
    public function load(ObjectManager $manager)
    {
        /** @var Shelf $shelf */
        $shelf = $this->getReference('shelf');

        // setting $book1...
        $book1->setShelf($shelf);
        $shelf->addBook($book1);

        $manager->persist($book1);

        // setting $book2...
        $book2->setShelf($shelf);
        $shelf->addBook($book2);

        $manager->persist($book2);

        // Setting $book3...
        $book3->setShelf($shelf);
        $shelf->addBook($book3);

        $manager->persist($book3);

        $manager->flush();
    }

    public function getOrder()
    {
        return 2;
    }
}

Here we implemented OrderFixtureInterface in class declarations. This tell us, that we need to implement getOrder() function which returns order number when fixture should load. To set Book relation for Shelf, we need first load shelf data, and set reference, as you can see in above example. When loading book data, we can get the reference to that shelf, and set it to books. Let’s run command one more time, which will remove previous data in database and load new data, with relations properly setted.