Files

65 lines
1.5 KiB
PHP
Raw Permalink Normal View History

2026-09-03 17:35:10 +01:00
<?php
declare(strict_types=1);
/**
* Applies any pending SQL migrations from migrations/*.sql, in filename order.
* Each applied file is recorded in the schema_migrations table so re-running is
* safe. Usage: php bin/migrate.php (or: composer migrate)
*/
use App\Support\Config;
use App\Support\Database;
require __DIR__ . '/../vendor/autoload.php';
$config = Config::load(dirname(__DIR__));
$pdo = (new Database($config->databasePath))->pdo();
$pdo->exec(
'CREATE TABLE IF NOT EXISTS schema_migrations (
filename TEXT PRIMARY KEY,
applied_at TEXT NOT NULL DEFAULT (strftime(\'%Y-%m-%dT%H:%M:%SZ\', \'now\'))
)'
);
$applied = $pdo->query('SELECT filename FROM schema_migrations')
->fetchAll(PDO::FETCH_COLUMN);
$files = glob(dirname(__DIR__) . '/migrations/*.sql') ?: [];
sort($files);
$count = 0;
foreach ($files as $file) {
$name = basename($file);
if (in_array($name, $applied, true)) {
continue;
}
$sql = (string) file_get_contents($file);
$pdo->beginTransaction();
try {
$pdo->exec($sql);
$record = $pdo->prepare('INSERT INTO schema_migrations (filename) VALUES (?)');
$record->execute([$name]);
$pdo->commit();
} catch (Throwable $e) {
$pdo->rollBack();
fwrite(STDERR, "Failed to apply {$name}: {$e->getMessage()}\n");
exit(1);
}
echo "Applied {$name}\n";
$count++;
}
echo $count === 0
? "Database is up to date; nothing to apply.\n"
: "Done. Applied {$count} migration(s).\n";