Installation:
composer require atournayre/fixtures-bundle --dev
Register the bundle in config/bundles.php:
return [
// ...
Hautelook\AliceBundle\HautelookAliceBundle::class => ['dev' => true, 'test' => true],
Atournayre\Bundle\FixtureBundle\AtournayreFixtureBundle::class => ['dev' => true, 'test' => true],
];
First Fixture File:
Create a YAML file (e.g., config/fixtures/users.yaml) with Alice syntax:
App\Entity\User:
user1:
email: 'user1@example.com'
password: '<hashPassword("password123")>'
roles: ['ROLE_USER']
Run Fixtures:
php bin/console fixtures
Use this bundle to seed your database with test data for development, testing, or demos. Ideal for:
Organize fixtures by entity or feature:
config/fixtures/
├── users.yaml # User entities
├── posts.yaml # Post entities (with user references)
└── categories.yaml # Category entities
Example: Related Entities
App\Entity\Post:
post1:
title: 'First Post'
content: 'Lorem ipsum...'
author: '<entity<user1, App\Entity\User>>' # Reference by fixture ID
category: '<entity<category1, App\Entity\Category>>'
Leverage built-in providers for dynamic values:
<uuidV4()>, <uuidV8(uuid)><currentDateWithTime(10:30)>, <randomHourWithDate()><hashPassword("plaintext")>Example: Dynamic UUIDs
App\Entity\Product:
product1:
id: '<uuidV4()>'
sku: '<uuidV8(product1)>'
Extend functionality with events:
Example Listener:
#[AsEventListener]
readonly class PostFixtureListener {
public function __invoke(AfterFixturesEvent $event): void {
$this->logger->info('Fixtures loaded. Triggering notifications...');
// Custom logic (e.g., send welcome emails)
}
}
Use fixtures in PHPUnit tests:
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class UserFixturesTest extends KernelTestCase {
public function testUserCreation(): void {
self::bootKernel();
$this->loadFixtures(['config/fixtures/users.yaml']);
$user = self::$container->get('doctrine')->getRepository(User::class)->findOneByEmail('user1@example.com');
$this->assertNotNull($user);
}
}
Circular References:
Avoid bidirectional relationships in fixtures (e.g., User ↔ Post where both reference each other). Use a clear hierarchy (e.g., load User first, then Post).
UUID Collisions:
If using <uuidV4()>, ensure uniqueness manually or via database constraints. Prefer <uuidV8(fixture_id)> for deterministic IDs.
Event Dispatcher Conflicts:
If using Symfony’s native event dispatcher, ensure AtournayreFixtureBundle is registered after your app’s bundles to avoid priority issues.
Password Hashing:
The <hashPassword()> provider uses Symfony’s PasswordHasher. Ensure your User entity’s password field is typed as string (not object or Password).
--dry-run flag to preview fixtures without loading:
php bin/console fixtures --dry-run
php bin/console fixtures -vv
yamllint).Custom Providers: Extend the bundle by creating a custom provider service. Example:
# config/services.yaml
services:
App\Fixture\Provider\CustomProvider:
tags: ['atournayre.fixture.provider']
Override Default Providers:
Replace built-in providers (e.g., DateTime) by binding your own service with the same tag:
tags: ['atournayre.fixture.provider.datetime']
Environment-Specific Fixtures: Use Symfony’s parameter system to load different fixtures per environment:
# config/fixtures/dev.yaml (loaded only in dev)
App\Entity\User:
dev_user:
email: 'dev@example.com'
$entityManager->getConnection()->beginTransaction();
try {
$this->loadFixtures(['file1.yaml', 'file2.yaml']);
$entityManager->getConnection()->commit();
} catch (\Exception $e) {
$entityManager->getConnection()->rollBack();
throw $e;
}
How can I help you explore Laravel packages today?