Reader Stacks

How to Create and Run Database Seeders in Laravel

Seeders populate the database with sample or default data — combined with factories, they're what makes a fresh local environment usable in seconds instead of requiring manual data entry.

Seeders populate the database with sample, default, or required baseline data — combined with model factories for generating realistic fake data, they're what turns a fresh clone of a project into a fully usable local environment in seconds, without any manual data entry.

Creating a seeder

php artisan make:seeder UserSeeder

A basic seeder with hardcoded data

class UserSeeder extends Seeder
{
    public function run(): void
    {
        DB::table('users')->insert([
            ['name' => 'Admin User', 'email' => 'admin@example.com', 'password' => Hash::make('password')],
            ['name' => 'Test User', 'email' => 'test@example.com', 'password' => Hash::make('password')],
        ]);
    }
}

A seeder using a model factory for realistic fake data

class UserSeeder extends Seeder
{
    public function run(): void
    {
        User::factory()->count(50)->create();

        User::factory()->create([
            'email' => 'admin@example.com',
            'is_admin' => true,
        ]);
    }
}

Combining a bulk of randomly-generated factory records with one or two specifically-configured records (like a known admin account) is a common, practical pattern — the bulk data gives you something realistic to test against, while the specific record gives you predictable, known credentials to actually log in with.

Calling seeders from the main DatabaseSeeder

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this->call([
            UserSeeder::class,
            CategorySeeder::class,
            ProductSeeder::class,
        ]);
    }
}

Listing seeders in $this->call() in a deliberate order matters when later seeders depend on data the earlier ones create — seeding products before categories, for instance, would fail if a product needs a valid category_id foreign key that doesn't exist yet.

Running seeders

php artisan db:seed                    // runs DatabaseSeeder, which calls the others
php artisan db:seed --class=UserSeeder // runs just one specific seeder

Running migrations and seeders together, fresh

php artisan migrate:fresh --seed

migrate:fresh drops every table and re-runs all migrations from scratch, and --seed runs DatabaseSeeder immediately afterward — a genuinely destructive command given it drops all existing data, appropriate for local development and CI, never for a production database with real data in it.

Seeders vs. factories: what each one is actually for

A factory defines how to generate a fake instance of a model (its attribute defaults, using a package like fakerphp/faker for realistic-looking random data) — a seeder decides how many and which specific records to actually create using that factory, or inserts specific hardcoded records directly. They're complementary, not alternatives to each other.