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.