Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sebastiaanluca/e4ee1659ff82884733f80372b0d34620 to your computer and use it in GitHub Desktop.
Save sebastiaanluca/e4ee1659ff82884733f80372b0d34620 to your computer and use it in GitHub Desktop.
Simple Laravel database state system to ensure database content is up-to-date (in addition to its schema using migrations).
<?php
declare(strict_types=1);
use App\Domain\Users\User;
use App\State;
use Illuminate\Support\Facades\Hash;
return new class extends State {
public function up(): void
{
$attributes = array_merge(
['email_verified_at' => now()],
config('app.owner'),
);
$attributes['password'] = Hash::make($attributes['password']);
User::create($attributes);
}
public function skipIf(): bool
{
return User::query()
->where('email', config('app.owner.email'))
->exists();
}
};
<?php
declare(strict_types=1);
use App\Domain\Elasticsearch\Elasticsearch;
use App\State;
return new class extends State {
public function up(): bool
{
return Elasticsearch::indices()
->deleteIndexTemplate(['name' => 'map_numerics_to_doubles'])
->asBool();
}
public function skipIf(): bool
{
return ! Elasticsearch::indices()
->existsIndexTemplate(['name' => 'map_numerics_to_doubles'])
->asBool();
}
};
<?php
declare(strict_types=1);
namespace App\Console\Commands;
use App\State;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use RuntimeException;
class EnsureDatabaseState extends Command
{
/**
* @var string
*/
protected $signature = 'db:ensure-state';
/**
* @var string
*/
protected $description = 'Ensure the database is in the correct state';
public function __construct(private readonly Filesystem $filesystem)
{
parent::__construct();
}
public function handle(): int
{
$this->components->info('Preparing state of database.');
$files = $this->filesystem->files(database_path('states'));
collect($files)
->map(fn (string $path): array => [
'path' => basename($path, '.php'),
'state' => $this->filesystem->getRequire($path),
])
->each($this->verify(...))
->each($this->runUp(...));
return static::SUCCESS;
}
private function verify(array $file): void
{
['state' => $state] = $file;
if ($state instanceof State) {
return;
}
throw new RuntimeException(sprintf('State "%s" must be an instance of "App\State"', $state));
}
private function runUp(array $file): void
{
['path' => $path, 'state' => $state] = $file;
if (method_exists($state, 'skipIf') && $state->skipIf()) {
$success = true;
} else {
$success = $state->up() ?? true;
}
$this->components->task($path, static fn (): bool => $success);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment