seedproject-web/api/app/Services/Migrator.php

58 lines
1.7 KiB
PHP
Raw Permalink Normal View History

<?php
namespace App\Services;
use PDO;
/** Applies ordered *.sql files from a migrations dir, tracked in a `migrations` table. */
class Migrator
{
private PDO $pdo;
private string $dir;
public function __construct(PDO $pdo, string $dir)
{
$this->pdo = $pdo;
$this->dir = $dir;
}
public function ensureTable(): void
{
$this->pdo->exec(
"CREATE TABLE IF NOT EXISTS `migrations` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`filename` VARCHAR(255) NOT NULL UNIQUE,
`applied_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
);
}
/** @return string[] filenames already applied */
public function applied(): array
{
return $this->pdo->query("SELECT filename FROM `migrations`")->fetchAll(PDO::FETCH_COLUMN) ?: [];
}
/** @return string[] absolute paths of pending migrations, in order */
public function pending(): array
{
$all = glob($this->dir . '/*.sql') ?: [];
sort($all);
$applied = $this->applied();
return array_values(array_filter($all, fn($p) => !in_array(basename($p), $applied, true)));
}
/** @return string[] filenames applied this run */
public function migrate(): array
{
$this->ensureTable();
$done = [];
foreach ($this->pending() as $path) {
$this->pdo->exec((string) file_get_contents($path));
$stmt = $this->pdo->prepare("INSERT IGNORE INTO `migrations` (filename) VALUES (?)");
$stmt->execute([basename($path)]);
$done[] = basename($path);
}
return $done;
}
}