Installation
composer require apie/fixtures --dev
Note: This package is designed for development/testing only. Exclude it from production via require-dev in composer.json.
First Use Case: Test Data Generation
use Apie\Fixtures\Factory\Factory;
use Apie\Fixtures\Factory\FactoryBuilder;
// Create a factory for a User model
$factory = FactoryBuilder::create()
->withModel(\App\Models\User::class)
->withFaker()
->build();
// Generate a single record
$user = $factory->create();
// Generate multiple records
$users = $factory->createMany(5);
Where to Look First
/vendor/apie/fixtures/src/Fixtures/ for predefined fixtures (e.g., UserFixture, PostFixture).create(), createMany(), and persist() (if using database fixtures).// Define a custom factory for a Post model
$postFactory = FactoryBuilder::create()
->withModel(\App\Models\Post::class)
->withFaker()
->withState([
'title' => 'Test Post',
'content' => fn() => 'Content for ' . $this->faker->word,
])
->build();
$post = $postFactory->create();
// Persist fixtures to the database (requires Eloquent)
$factory = FactoryBuilder::create()
->withModel(\App\Models\User::class)
->withFaker()
->withPersistence()
->build();
$factory->persist($user); // Single record
$factory->persistMany($users); // Multiple records
// Create a User with related Posts
$userFactory = FactoryBuilder::create()
->withModel(\App\Models\User::class)
->withFaker()
->build();
$postFactory = FactoryBuilder::create()
->withModel(\App\Models\Post::class)
->withFaker()
->withState(['user_id' => fn() => $userFactory->create()->id])
->build();
$user = $userFactory->create();
$posts = $postFactory->createMany(3);
Extend Apie\Fixtures\Fixture to create domain-specific fixtures:
use Apie\Fixtures\Fixture;
class CustomFixture extends Fixture
{
public function __construct()
{
$this->state([
'custom_field' => fn() => $this->faker->unique()->word,
]);
}
}
use Apie\Fixtures\Factory\FactoryBuilder;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$this->factory = FactoryBuilder::create()
->withModel(\App\Models\User::class)
->withFaker()
->withPersistence()
->build();
}
public function test_user_creation()
{
$user = $this->factory->create();
$this->assertDatabaseHas('users', ['email' => $user->email]);
}
}
Combine with Laravel Factories
Use Apie\Fixtures alongside Laravel’s built-in factories for hybrid approaches:
$factory = FactoryBuilder::create()
->withModel(\App\Models\User::class)
->withFaker()
->withState(fn() => \App\Models\User::factory()->raw())
->build();
Seeders Load fixtures in database seeders:
use Apie\Fixtures\Factory\FactoryBuilder;
class DatabaseSeeder extends Seeder
{
public function run()
{
$factory = FactoryBuilder::create()
->withModel(\App\Models\User::class)
->withFaker()
->withPersistence()
->build();
$factory->createMany(10);
}
}
API Testing Generate fixtures for API endpoints:
$user = $this->factory->create();
$response = $this->get("/api/users/{$user->id}");
$response->assertOk();
No ORM Dependency by Default
withPersistence() explicitly for Eloquent.Faker Initialization
withFaker():
->withFaker() // Required for faker-based state generation
State Overrides
withState() calls overwrite previous ones. Use mergeState() for additive behavior:
->withState(['field' => 'value'])
->mergeState(['field2' => 'value2']) // Preserves 'field'
Memory Leaks with Large Fixtures
createMany() loads all fixtures into memory. For large datasets, use batch processing:
$batchSize = 100;
for ($i = 0; $i < 1000; $i += $batchSize) {
$factory->persistMany($factory->createMany($batchSize));
}
Monorepo Maintenance
apie/fixtures repo is a proxy.Inspect Factory State Dump the factory’s current state before creation:
dump($factory->getState());
Enable Faker Debugging Configure Faker to log seed values:
$factory->withFaker()->withFakerSeed(1234)->withFakerDebug();
Validate Persistence Check if records were saved:
$this->assertDatabaseCount('users', 1);
Override Fixture Classes For debugging, replace a fixture class temporarily:
$factory->withFixture(new class extends \Apie\Fixtures\Fixture {
public function __construct() {
$this->state(['debug_field' => 'override']);
}
});
Custom Factory Builders
Extend FactoryBuilder to add domain-specific logic:
class CustomFactoryBuilder extends FactoryBuilder
{
public function withCustomState(array $state): self
{
$this->state($state);
return $this;
}
}
Plugin System Attach behaviors to factories via closures:
$factory = FactoryBuilder::create()
->withModel(\App\Models\User::class)
->withFaker()
->onCreate(fn($model) => $model->update(['active' => true]))
->build();
Fixture Events Listen for fixture creation events (requires event system integration):
event(new FixtureCreated($fixture, $model));
Hybrid Factories
Combine with Laravel’s Model::factory() for dynamic state:
$factory->withState(fn() => \App\Models\User::factory()->state(['role' => 'admin'])->raw());
How can I help you explore Laravel packages today?