How to load Doctrine fixtures in Symfony

Fixture data gives a Symfony project repeatable database rows for tests, demos, and local development without copying production records. DoctrineFixturesBundle reads fixture classes from the application container and writes the objects they create through Doctrine ORM.

Using the test environment keeps the load command pointed at a disposable database. The same fixture class can seed a development database, but the default load command purges existing rows before inserting fixture data.

Start from a Symfony project where Doctrine is configured and the target entity already exists. A mapped App\Entity\Product entity with a name field is enough to show the data flow from fixture class to database row, and doctrine:query:dql confirms that Doctrine can read the loaded rows.

Steps to load Doctrine fixtures in Symfony:

  1. Open a terminal in the Symfony project root that contains bin/console.
  2. Install DoctrineFixturesBundle as a development dependency.
    $ composer require --dev doctrine/doctrine-fixtures-bundle
    ./composer.json has been updated
    Installing dependencies from lock file
      - Installing doctrine/data-fixtures
      - Installing doctrine/doctrine-fixtures-bundle
    Executing script cache:clear [OK]

    Symfony Flex registers the bundle for development and test use when the package is installed with --dev.

  3. Point the test environment at a disposable database.
    DATABASE_URL="sqlite:///%kernel.project_dir%/var/app_test.db"

    Use a database reserved for fixture loading. Loading fixtures can erase existing rows unless --append is used.
    Related: How to configure a SQLite database in Symfony

  4. Create the fixture class that inserts the sample rows.
    src/DataFixtures/AppFixtures.php
    <?php
     
    namespace App\DataFixtures;
     
    use App\Entity\Product;
    use Doctrine\Bundle\FixturesBundle\Fixture;
    use Doctrine\Persistence\ObjectManager;
     
    final class AppFixtures extends Fixture
    {
        public function load(ObjectManager $manager): void
        {
            foreach (['Starter kit', 'Fixture sample'] as $name) {
                $product = new Product();
                $product->setName($name);
     
                $manager->persist($product);
            }
     
            $manager->flush();
        }
    }

    Replace Product and setName() with the entity class and setters used by the project.

  5. Create the schema in the empty test database.
    $ php bin/console --env=test doctrine:schema:create
     
     ! [CAUTION] This operation should not be executed in a production environment!
     
     Creating database schema...
     
     [OK] Database schema created successfully!

    Run migrations instead when the target database already follows the project migration workflow.
    Related: How to run Doctrine migrations in Symfony

  6. Load the fixture data into the test database.
    $ php bin/console --env=test doctrine:fixtures:load --no-interaction
       > purging database
       > loading App\DataFixtures\AppFixtures

    The load command purges the target database before loading fixtures by default. Keep the --env value pointed at a disposable database, or add --append when existing rows must stay.

  7. Query the fixture rows from Doctrine.
    $ php bin/console --env=test doctrine:query:dql 'SELECT p.id, p.name FROM App\Entity\Product p ORDER BY p.id'
     array(2) {
      [0]=>
      array(2) {
        ["id"]=>
        int(1)
        ["name"]=>
        string(11) "Starter kit"
      }
      [1]=>
      array(2) {
        ["id"]=>
        int(2)
        ["name"]=>
        string(14) "Fixture sample"
      }
    }