Skip to content

Instantly share code, notes, and snippets.

@LarryBarker
Created September 16, 2024 02:55
Show Gist options
  • Save LarryBarker/a7dd02791cc3a3f41ca61b913d322fa2 to your computer and use it in GitHub Desktop.
Save LarryBarker/a7dd02791cc3a3f41ca61b913d322fa2 to your computer and use it in GitHub Desktop.
The CanSeedOncePerDatabase trait for Laravel projects ensures that database seeders are only executed once per database.
<?php
namespace Database\Seeders;
use Illuminate\Console\View\Components\TwoColumnDetail;
use Illuminate\Support\Facades\DB;
trait CanSeedOncePerDatabase
{
protected string $seedersTable = 'seeders';
protected bool $seedersTableExists = false;
public function callOncePerDatabase($class, $silent = false, array $parameters = []): void
{
if ($this->seederHasAlreadyBeenCalled($class)) {
if ($silent === false && isset($this->command)) {
with(new TwoColumnDetail($this->command->getOutput()))->render(
$class,
'<fg=gray>Seeder had already run on this database</> <fg=yellow;options=bold>SKIPPING</>'
);
$this->command->getOutput()->writeln('');
}
return;
}
$this->call($class, $silent, $parameters);
$this->markSeederAsCalled($class);
}
protected function seederHasAlreadyBeenCalled($class): bool
{
$this->createSeedersTableIfNotExists();
return DB::table($this->seedersTable)
->where('seeder', $class)
->exists();
}
protected function markSeederAsCalled($class): void
{
$this->createSeedersTableIfNotExists();
DB::table($this->seedersTable)
->insert(['seeder' => $class]);
}
protected function createSeedersTableIfNotExists(): void
{
if ($this->seedersTableExists) {
return;
}
$schema = DB::connection()->getSchemaBuilder();
if (! $schema->hasTable($this->seedersTable)) {
$schema->create($this->seedersTable, function ($table) {
$table->string('seeder')->unique();
});
}
$this->seedersTableExists = true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment