zenstruck/foundry
Expressive, autocompletable fixture factories for Symfony + Doctrine (ORM and/or MongoDB). Create random-but-valid entities on demand for fixtures and tests, with states, persistence helpers, and rich testing features via ZenstruckFoundryBundle.
Zenstruck/FoundryBundle (or manual integration). Its factory pattern aligns with Laravel’s native create()/factory() methods, reducing cognitive overhead.published(), withAuthor()) mirror DDD language, making fixtures self-documenting and maintainable in complex domains.#[AsFoundryHook] attribute and event dispatching enable granular control over fixture lifecycle (e.g., pre/post-persistence logic), useful for side effects like notifications or caching.doctrine/orm + doctrine/doctrine-bundle (Laravel uses doctrine/dbal under the hood, but ORM integration is seamless).Zenstruck/FoundryBundle) and Pest (via community packages like pestphp/foundry).Factory facade with Foundry factories (e.g., PostFactory::new() instead of Post::factory()).make:factory scaffolding).ResetDatabase) but provides migration guides.#[AsFoundryHook]) require understanding of Symfony’s event system, which may be unfamiliar to Laravel devs.withoutDoctrineEvents().auto_refresh: false in config.FOUNDRY_FAKER_SEED) can cause flaky tests if not scoped properly (e.g., per-test-case seeds).DatabaseMigrations or DatabaseTransactions? (Foundry v2.9+ deprecates ResetDatabase trait in favor of built-in reset mechanisms.)make:factory fixtures migrate to Foundry’s syntax? Tooling like php artisan foundry:upgrade (if available) or custom scripts may be needed.php bin/console doctrine:fixtures:load).create()/factory() with Foundry’s fluent methods (e.g., UserFactory::new()->admin()->create()).State objects for reusable fixture states (e.g., PublishedState, DraftState).make:factory scaffolding).KernelEvents, DoctrineEvents).User, Post) to test Foundry’s expressiveness.create() vs. Factory::new()->create()).php artisan foundry:make:factory (if available) or adapt Laravel’s make:factory to output Foundry syntax.// Before (Laravel)
$user = User::factory()->admin()->create();
// After (Foundry)
$user = UserFactory::new()->admin()->create();
composer.json:
"require-dev": {
"zenstruck/foundry": "^2.10",
"zenstruck/foundry-bundle": "^2.10"
}
config/packages/zenstruck_foundry.yaml:
zenstruck_foundry:
auto_refresh: true # Enable for relationship consistency
faker_seed: random # Or 'fixed' for reproducible tests
Zenstruck/FoundryBundle with FoundryExtension.pestphp/foundry and configure in pest.php:
uses(FoundryTestCase::class)->in('Feature');
| Feature | Laravel Native | Foundry Support | Notes |
|---|---|---|---|
| Factory Methods | ✅ | ✅ | Fluent syntax (->admin()). |
| Relationships | ✅ | ✅ | Auto-refresh ensures consistency. |
| State Management | ❌ | ✅ | Reusable states (e.g., PublishedState). |
| Doctrine Fixtures | ❌ | ✅ | Integrates with DoctrineFixturesBundle. |
| Faker Customization | ✅ | ✅ | Extend FoundryFaker class. |
| Test Isolation | ✅ (Transactions) | ✅ (Auto-Reset) | Foundry v2.9+ has built-in reset. |
| Event Hooks | ❌ | ✅ | #[AsFoundryHook] attribute. |
User, Post, Product factories to Foundry.factory() calls in tests with Factory::new().auto_refresh: true and test bidirectional relationships (e.g., User->Posts).withoutDoctrineEvents() in unit tests to avoid event overhead.DoctrineFixturesBundle for bulk data loading.DATABASE_RESET_MODE=migrate).#[AsFoundryHook] for complex lifecycle logic.->published()->withTags()) act as living documentation.make:factory scaffolding or manual Faker setup.Factory::debug() to inspect generated data.How can I help you explore Laravel packages today?