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; } }