Skip to main content

Factories, Seeders, and Database Testing

12/28
Chapter 3 Eloquent ORM and Database Mastery

Factories, Seeders, and Database Testing

18 min read Lesson 12 / 28

Model Factories and Database Seeding

Factories generate realistic fake data for testing and development. Seeders populate your database with initial data.

Creating a Factory

php artisan make:factory PostFactory
class PostFactory extends Factory
{
    protected $model = Post::class;

    public function definition(): array
    {
        return [
            'user_id' => User::factory(),
            'category_id' => Category::factory(),
            'title' => fake()->sentence(),
            'slug' => fake()->unique()->slug(),
            'excerpt' => fake()->paragraph(),
            'body' => fake()->paragraphs(5, true),
            'is_published' => fake()->boolean(80),
            'published_at' => fake()->dateTimeBetween('-1 year'),
            'views_count' => fake()->numberBetween(0, 10000),
        ];
    }

    // Factory states for specific scenarios
    public function published(): static
    {
        return $this->state(fn () => [
            'is_published' => true,
            'published_at' => fake()->dateTimeBetween('-6 months'),
        ]);
    }

    public function draft(): static
    {
        return $this->state(fn () => [
            'is_published' => false,
            'published_at' => null,
        ]);
    }

    public function featured(): static
    {
        return $this->state(fn () => [
            'is_featured' => true,
        ]);
    }
}

Using Factories

// Single model
$post = Post::factory()->create();

// With state
$post = Post::factory()->published()->featured()->create();

// Multiple models
$posts = Post::factory()->count(50)->published()->create();

// With relationships
$user = User::factory()
    ->has(Post::factory()->count(10)->published())
    ->create();

Database Seeders

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        // Create admin user
        User::factory()->create([
            'name' => 'Admin',
            'email' => 'admin@example.com',
        ]);

        // Create categories
        $categories = Category::factory()->count(8)->create();

        // Create users with posts
        User::factory()
            ->count(20)
            ->has(Post::factory()->count(5)->state(fn () => [
                'category_id' => $categories->random()->id,
            ]))
            ->create();
    }
}

Run with: php artisan db:seed

Factories are essential for testing — they let you create exactly the data your test needs without manual setup.