Skip to content

Idempotent Seeding

The starter implements an idempotent seeding system that allows database seeders to run multiple times safely without creating duplicate data or causing errors. This is critical for production environments where you need to update seed data without rebuilding the entire database.

Idempotent means an operation can be performed multiple times without changing the result beyond the initial application.

In the context of database seeders:

  • Running a seeder once creates the expected data
  • Running it again doesn’t create duplicates
  • Running it a third time still produces the same result
  • Data is updated if it exists, created if it doesn’t

Tables that are idempotently seeded typically follow a common schema: a unique slug mapped to an enum case, a label, and potentially other descriptive fields.

The App\Domains\Core\Seeders\IdempotentSeeder can be used to populate such tables easily. It handles INSERT, UPDATE, and DELETE operations based on the values it’s given. If something is removed or modified, the seeder will handle the change appropriately. It is aware of the SoftDeletes trait and can set (or unset) the deleted_at column correctly.

To register an idempotent seeder to be run by db:seed and during deployments, provide the #[AutoSeed] attribute on the seeder class. It will be automatically discovered and executed.

If the data relies on other tables being seeded first, you can specify dependencies using the dependsOn parameter:

#[AutoSeed(dependsOn: [OtherSeeder::class])]
class MySeeder extends IdempotentSeeder
{
// ...
}

Provided below is an example of a simple idempotent seeder. The $model property must be provided. The data() method can get data from anywhere; this example is an implementation for an enum.

Schema::create('product_statuses', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
$table->string('label');
$table->tinyInteger('order_index')->default(5);
$table->timestamps();
$table->softDeletes();
});
Terminal window
php artisan db:seed:list

This shows:

  • Seeder class names
  • Their dependencies
  • Execution order