Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions src/Seeders/Seeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);

namespace Foxdb\Seeders;

/**
* Abstract Seeder — base class for all database seeders.
*
* Seeders populate the database with test or default data. Unlike
* migrations, seeders are not tracked: they can be run any number
* of times and should be written to be idempotent when that matters.
*
* Usage:
* class UsersSeeder extends Seeder
* {
* public function run(): void
* {
* DB::table('users')->insert([
* 'name' => 'Admin',
* 'email' => 'admin@example.com',
* ]);
*
* // Optionally call other seeders
* $this->call(RolesSeeder::class);
* }
* }
*/
abstract class Seeder
{
/**
* The database connection name to run this seeder on.
* Null means the current default connection.
*
* @var string|null
*/
public ?string $connection = null;

/**
* The SeederRunner currently executing this seeder.
* Injected by the runner so $this->call() can delegate back to it.
*
* @var SeederRunner|null
*/
protected ?SeederRunner $runner = null;

/**
* Apply the seeder — insert default or test data.
*
* @return void
*/
abstract public function run(): void;

/**
* Inject the runner that is executing this seeder.
*
* @param SeederRunner $runner
* @return void
*/
public function setRunner(SeederRunner $runner): void
{
$this->runner = $runner;
}

/**
* Run one or more other seeders from inside this seeder.
*
* @param string|array<int, string> $seeders Class name(s) of seeders to run
* @return array<int, SeederResult>
*/
public function call(string|array $seeders): array
{
$seeders = is_array($seeders) ? $seeders : [$seeders];
$results = [];

foreach ($seeders as $class) {
$results[] = $this->runner !== null
? $this->runner->runClass($class)
: SeederResult::fail($class, 0.0, 'No runner attached to seeder.');
}

return $results;
}
}
58 changes: 58 additions & 0 deletions src/Seeders/SeederResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Foxdb\Seeders;

/**
* SeederResult — immutable record of a single seeder execution.
*/
final class SeederResult
{
/**
* @param string $name Seeder class name (with or without namespace)
* @param bool $success Whether it completed without error
* @param float $timeMs Execution time in milliseconds
* @param string $error Error message if $success = false
*/
public function __construct(
public readonly string $name,
public readonly bool $success,
public readonly float $timeMs,
public readonly string $error = '',
) {}

/**
* Convenience constructor for a successful result.
*/
public static function ok(string $name, float $timeMs): self
{
return new self($name, true, $timeMs);
}

/**
* Convenience constructor for a failed result.
*/
public static function fail(string $name, float $timeMs, string $error): self
{
return new self($name, false, $timeMs, $error);
}

/**
* Human-readable one-line summary.
*
* @return string
*/
public function toString(): string
{
$status = $this->success ? 'OK' : 'FAILED';
$time = number_format($this->timeMs, 2);
$line = "[{$status}] seed {$this->name} ({$time} ms)";

if (! $this->success && $this->error !== '') {
$line .= " — {$this->error}";
}

return $line;
}
}
Loading
Loading