Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Simple Doctrine Data Fixtures

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

"Data fixtures" is the name given to dummy data that you add to your app while developing or running tests to make life easier. It's a lot nicer to work on a new feature when you actually have decent data in your database. We created some data fixtures, in a sense, via this new action. But Doctrine has a system specifically designed for this.

Installing DoctrineFixturesBundle

Search for "doctrinefixturesbundle" to find its GitHub repository. And you can actually read its documentation over on Symfony.com. Copy the install line and, at your terminal, run it:

composer require --dev orm-fixtures

orm-fixtures is, of course, a Flex alias, in this case, to doctrine/doctrine-fixtures-bundle. And... done! Run

git status

to see that this added a bundle, as well as a new src/DataFixtures/ directory. Go open that up. Inside, we have a single new file called AppFixtures.php.

... lines 1 - 7
class AppFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
// $product = new Product();
// $manager->persist($product);
$manager->flush();
}
}

DoctrineFixturesBundle is a delightfully simple bundle. It gives us a new console command called doctrine:fixtures:load. When we run this, it will empty our database and then execute the load() method inside of AppFixtures. Well, it will actually execute the load() method on any service we have that extends this Fixture class. So we could have multiple classes in this directory if we want.

If we run it right now... with an empty load() method, it clears our database, calls that blank method, and... the result over on the "Browse" page is that we have nothing!

php bin/console doctrine:fixtures:load

Filling in the load() Method

That's not very interesting, so let's go fill in that load() method! Start in MixController: steal all of the VinylMix code... and paste it here. Hit "Ok" to add the use statement.

... lines 1 - 10
public function load(ObjectManager $manager): void
{
$mix = new VinylMix();
$mix->setTitle('Do you Remember... Phil Collins?!');
$mix->setDescription('A pure mix of drummers turned singers!');
$genres = ['pop', 'rock'];
$mix->setGenre($genres[array_rand($genres)]);
$mix->setTrackCount(rand(5, 20));
$mix->setVotes(rand(-50, 50));
$manager->flush();
}
... lines 23 - 24

Notice the load() method accepts some ObjectManager argument. That's actually the EntityManager, since we're using the ORM. If you look down here, it already has the flush() call. The only thing we're missing is the persist() call: $manager->persist($mix).

... lines 1 - 10
public function load(ObjectManager $manager): void
{
... lines 13 - 19
$manager->persist($mix);
... lines 21 - 22
}
... lines 24 - 25

So the variable is called $manager here... but these two lines are exactly what we have our controller: persist() and flush().

Try the command again:

php bin/console doctrine:fixtures:load

It empties the database, executes our fixtures, and we have... one new mix!

Okay, this is kind of cool. We have a new bin/console command to load stuff. But for developing, I want a really rich set of data fixtures, like... maybe 25 mixes. We could add those by hand here... or even create a loop. But there's a better way, via a library called "Foundry". Let's explore it next!

Leave a comment!

7
Login or Register to join the conversation
ssi-anik Avatar

With symfony console doctrine:fixtures:load --append it will append data.

2 Reply
Andrey Avatar

Fixture classes probably should be excluded from deployment, if composer install --no-dev is used on the server?

Reply

Hey Andrey,

Yes, you could exclude or remove the fixtures on your production server for an extra (but tiny) performance boost.

Cheers!

Reply
Andrey Avatar

Unrelated question – why am I always switched to Spanish version of SymfonyCasts, when I click on a reply notifications under the bell icon? :)

Reply

Ohh, that's unexpected :) - I'll investigate what's going on

Reply
Andrey Avatar

Thanks, but it's more important than performance boost. Class AppFixtures extends a class which will not exist in production environment.

Reply

Yea, that's a good point, but as long as nothing in your production code depends on those classes, you should be fine. Otherwise, you'll need to find a way to remove them from production. An easy way would be just to add a specific prod config to exclude the "DataFixtures" directory from being autoregistered.

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=8.1",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "babdev/pagerfanta-bundle": "^3.7", // v3.7.0
        "doctrine/doctrine-bundle": "^2.7", // 2.7.0
        "doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
        "doctrine/orm": "^2.12", // 2.12.3
        "knplabs/knp-time-bundle": "^1.18", // v1.19.0
        "pagerfanta/doctrine-orm-adapter": "^3.6", // v3.6.1
        "pagerfanta/twig": "^3.6", // v3.6.1
        "sensio/framework-extra-bundle": "^6.2", // v6.2.6
        "stof/doctrine-extensions-bundle": "^1.7", // v1.7.0
        "symfony/asset": "6.1.*", // v6.1.0
        "symfony/console": "6.1.*", // v6.1.2
        "symfony/dotenv": "6.1.*", // v6.1.0
        "symfony/flex": "^2", // v2.2.2
        "symfony/framework-bundle": "6.1.*", // v6.1.2
        "symfony/http-client": "6.1.*", // v6.1.2
        "symfony/monolog-bundle": "^3.0", // v3.8.0
        "symfony/proxy-manager-bridge": "6.1.*", // v6.1.0
        "symfony/runtime": "6.1.*", // v6.1.1
        "symfony/twig-bundle": "6.1.*", // v6.1.1
        "symfony/ux-turbo": "^2.0", // v2.3.0
        "symfony/webpack-encore-bundle": "^1.13", // v1.15.1
        "symfony/yaml": "6.1.*", // v6.1.2
        "twig/extra-bundle": "^2.12|^3.0", // v3.4.0
        "twig/twig": "^2.12|^3.0" // v3.4.1
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
        "symfony/debug-bundle": "6.1.*", // v6.1.0
        "symfony/maker-bundle": "^1.41", // v1.44.0
        "symfony/stopwatch": "6.1.*", // v6.1.0
        "symfony/web-profiler-bundle": "6.1.*", // v6.1.2
        "zenstruck/foundry": "^1.21" // v1.21.0
    }
}
userVoice