If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
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.
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
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!
Fixture
classes probably should be excluded from deployment, if composer install --no-dev
is used on the server?
Hey Andrey,
Yes, you could exclude or remove the fixtures on your production server for an extra (but tiny) performance boost.
Cheers!
Unrelated question – why am I always switched to Spanish version of SymfonyCasts, when I click on a reply notifications under the bell icon? :)
Thanks, but it's more important than performance boost. Class AppFixtures
extends a class which will not exist in production environment.
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!
// 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
}
}
With
symfony console doctrine:fixtures:load --append
it will append data.