Doctrine

Environment Specific Doctrine Datafixtures

When working on a Symfony project the database you will most likely be working with is doctrine. A bundle used on doctrine you can use in your projects is called data fixtures.

Data fixtures are used to load a controlled set of data into the database. This is perfect to add test data into your application to make sure it is running correctly or you can use it to load initial data required by the application.

To run the doctrine data fixtures in Symfony you can set the --env flag to define what environment database to use. The problem you will find with your data fixtures is that you can't split up data fixtures to be for certain environments. This means you can't have some data fixtures for development environment and other data fixtures for the production environment.

In this tutorial we are going to learn how we can define data fixtures to only be used in certain environments.

Extending The AbstractFixture

The first step we need to do is extend the AbstractFixture class this is the class that your data fixtures will extend. From this class we are going to intercept the load method, access the application container, check the current environment, check the defined environment for the data fixture matches the current environment.

<?php
namespace DatabaseBundle\DataFixtures;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\KernelInterface;

abstract class AbstractDataFixture extends AbstractFixture implements ContainerAwareInterface, FixtureInterface, OrderedFixtureInterface
{
    /**
     * {@inheritDoc}
     */
    public function load(ObjectManager $manager)
    {
        // Check if the data fixture has a doAlways method and always run this in any environment
        if(method_exists( $this, 'doAlways'))
        {
            $this->doAlways($manager);
        }

        // Check if the current environment in production and if the doProd method exists
        if($this->getCurrentEnvironment() == 'prod' && method_exists( $this, 'doProd'))
        {
            $this->doProd($manager);
        }

        // Check if the current environment is available in the list of environments assigned to the data fixture
        if (in_array($this->getCurrentEnvironment(), $this->getEnvironments()))
        {
            $this->doLoad($manager);
        }
    }

    /**
     * @return string
     */
    public function getCurrentEnvironment()
    {
        /** @var KernelInterface $kernel */
        $kernel = $this->container->get('kernel');
        return $kernel->getEnvironment();
    }

    /**
     * Perform the database objects
     * @param ObjectManager $manager The object manager.
     */
    abstract protected function doLoad(ObjectManager $manager);

    /**
     * Get the environments the data fixtures are ran on
     * @return array The name of the environments.
     */
    abstract protected function getEnvironments();
}

Dev Only Data Fixture

Below is an example we can use to load User data only in the Dev environment. Create your data fixtures and extend the new class AbstractDataFixture, enter the data you want to load inside the doLoad() method.

Inside the getEnvironments() method define an array of all the environments that can use this data fixture. In this example we are running this on the test and dev environment only.

<?php
namespace DatabaseBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use DatabaseBundle\DataFixtures\AbstractDataFixture;
use DatabaseBundle\Entity\User;

/**
 * DevUserData
 */
class DevUserData extends AbstractDataFixture
{
    /**
     * Get the order of this fixture
     *
     * @return integer
     */
    public function getOrder()
    {
        return 1;
    }

    /**
     * {@inheritDoc}
     */
    protected function doLoad(ObjectManager $manager)
    {
        $user = new User();
        $user->setUsername('TestUser');
        $user->setPassword('pw');
        $manager->persist($user);

        $user = new User();
        $user->setUsername('TestUser2');
        $user->setPassword('pw');
        $manager->persist($user);

        $user = new User();
        $user->setUsername('TestUser3');
        $user->setPassword('pw');
        $manager->persist($user);

        $user = new User();
        $user->setUsername('TestUser4');
        $user->setPassword('pw');
        $manager->persist($user);

        $user = new User();
        $user->setUsername('TestUser5');
        $user->setPassword('pw');
        $manager->persist($user);

        $manager->flush();
    }

    /**
     * {@inheritDoc}
     */
    protected function getEnvironments()
    {
        return ['test', 'dev'];
    }
}

Data Fixture For All Environments

Below is an example of how you would load production data into your application but for this we are going to load in all environments. Again create a new data fixture and extend from the AbstractDataFixture class. Add the data you want to load in the doLoad method and then create an array of the environments you want this to run in.

<?php
namespace DatabaseBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

use DatabaseBundle\DataFixtures\AbstractDataFixture;
use DatabaseBundle\Entity\User;

/**
 * ProdUserData
 */
class ProdUserData extends AbstractDataFixture
{
    /**
     * Get the order of this fixture
     *
     * @return integer
     */
    public function getOrder()
    {
        return 2;
    }

    /**
     * {@inheritDoc}
     */
    protected function doLoad(ObjectManager $manager)
    {
        $user = new User();
        $user->setUsername('AdminUser');
        $user->setPassword('pw');
        $manager->persist($user);

        $manager->flush();
    }

    /**
     * {@inheritDoc}
     */
    protected function getEnvironments()
    {
        return ['prod', 'staging', 'test', 'dev'];
    }
}
Back to top

Fastest WordPress Hosting With WPEngine

Stunning speed, powerful security, and best-in-class customer service. At WP Engine.

Risk free for 60 days