doctrine/doctrine-fixtures-bundle
Symfony bundle integrating DoctrineFixtures: define and load sample data (fixtures) into your database for dev, tests, and demos. Supports grouping, ordering, and environment-aware loading via CLI commands, with easy integration into the Doctrine ORM workflow.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require doctrine/doctrine-fixtures-bundle
Add the bundle to config/bundles.php:
return [
// ...
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['all' => true],
];
First Fixture:
Create a fixture class in src/DataFixtures/ (e.g., UserFixtures.php):
namespace App\DataFixtures;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use App\Entity\User;
class UserFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
$user = new User();
$user->setName('Test User');
$manager->persist($user);
$manager->flush();
$this->addReference('user', $user); // Reference for later fixtures
}
}
Run Fixtures:
php bin/console doctrine:fixtures:load
php bin/console doctrine:fixtures:loadphp bin/console doctrine:fixtures:load --fixtures=App\DataFixtures\UserFixturesphp bin/console doctrine:fixtures:load --dry-run (4.3.0+)php bin/console doctrine:fixtures:load --purge-with-truncatesrc/DataFixtures/ directory (default location for fixtures)config/packages/doctrine.yaml (for custom purging strategies)Group fixtures by domain (e.g., UserFixtures, ProductFixtures, OrderFixtures) and use dependencies to enforce load order:
// OrderFixtures.php
public function load(ObjectManager $manager)
{
$this->addDependency(UserFixtures::class); // Loads UserFixtures first
// ...
}
Extend base fixtures for shared logic:
abstract class BaseUserFixture extends Fixture
{
protected function createUser(string $name): User
{
$user = new User();
$user->setName($name);
return $user;
}
}
Use Faker for realistic test data:
use Faker\Factory;
public function load(ObjectManager $manager)
{
$faker = Factory::create();
for ($i = 0; $i < 10; $i++) {
$user = new User();
$user->setEmail($faker->email);
$manager->persist($user);
}
$manager->flush();
}
Reference entities to build relationships:
// UserFixtures.php
$this->addReference('admin', $adminUser);
// RoleFixtures.php
public function load(ObjectManager $manager)
{
$user = $this->getReference('admin');
$user->addRole('ROLE_ADMIN');
$manager->flush();
}
php bin/console doctrine:database:drop --force && php bin/console doctrine:database:create && php bin/console doctrine:fixtures:load--append to add fixtures without purging:
php bin/console doctrine:fixtures:load --append
php bin/console doctrine:fixtures:load --dry-run
--parallel (if supported by your Doctrine version):
php bin/console doctrine:fixtures:load --parallel
Override default purging (e.g., soft-delete instead of truncate):
# config/packages/doctrine_fixtures.yaml
doctrine_fixtures:
purgers:
orm:
Doctrine\Bundle\FixturesBundle\Purger\ORMPurger: ~
# Custom purger (e.g., for soft-deletes)
App\Fixtures\SoftDeletePurger: ~
Trigger fixtures on kernel events (e.g., kernel.terminate):
// src/EventListener/FixtureLoaderListener.php
public function onKernelTerminate(KernelEvent $event)
{
if ($event->isMasterRequest()) {
$this->container->get('doctrine.fixtures.loader')->load();
}
}
Create custom commands for complex workflows:
// src/Command/SeedCommand.php
use Doctrine\Bundle\FixturesBundle\Command\LoadDataFixturesDoctrineCommand;
class SeedCommand extends LoadDataFixturesDoctrineCommand
{
protected function getFixtures(): array
{
return [App\DataFixtures\SeedFixtures::class];
}
}
Use fixtures in PHPUnit tests:
public function testUserCreation()
{
$this->loadFixtures([UserFixtures::class]);
$user = $this->getEntityManager()->getRepository(User::class)->findOneByName('Test User');
$this->assertNotNull($user);
}
Circular Dependencies
addDependency() carefully or restructure fixtures.Transaction Rollbacks
try-catch blocks or split large fixtures into smaller ones.Reference Scope
getReference() with the exact class name (e.g., UserFixtures::REFERENCE_KEY).Performance with Large Datasets
--parallel (if supported) or batch inserts:
$batchSize = 100;
for ($i = 0; $i < 1000; $i += $batchSize) {
$manager->flush();
$manager->clear();
}
Verbose Output Enable debug mode for detailed logs:
php bin/console doctrine:fixtures:load -vvv
Dry-Run Test fixtures without applying changes:
php bin/console doctrine:fixtures:load --dry-run
Custom Logger Inject a logger to track fixture execution:
use Psr\Log\LoggerInterface;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function load(ObjectManager $manager)
{
$this->logger->info('Loading UserFixtures...');
// ...
}
Purger Customization
ORMPurger (truncates tables), TruncatePurger (faster but less safe).// src/Fixtures/SoftDeletePurger.php
use Doctrine\Bundle\FixturesBundle\Purger\PurgerInterface;
class SoftDeletePurger implements PurgerInterface
{
public function purge(ObjectManager $manager): void
{
$manager->createQuery('UPDATE App\Entity\User u SET u.deletedAt = CURRENT_TIMESTAMP')->execute();
}
}
config/packages/doctrine_fixtures.yaml:
doctrine_fixtures:
purgers:
orm:
App\Fixtures\SoftDeletePurger: ~
Exclusion Patterns Exclude specific fixtures from loading:
# config/packages/doctrine_fixtures.yaml
doctrine_fixtures:
exclude:
- App\DataFixtures\Staging\*
Environment-Specific Fixtures Load different fixtures per environment:
# Load only production fixtures
php bin/console doctrine:fixtures:load --env=prod --fixtures=App\DataFixtures\Production\*
How can I help you explore Laravel packages today?