39038-vm/db/migrate.php
2026-03-08 13:14:36 +00:00

93 lines
3.2 KiB
PHP

<?php
// db/migrate.php - Run pending migrations
// Ensure we are in the correct directory context if run from CLI
if (php_sapi_name() === 'cli' && !defined('DB_HOST')) {
require_once __DIR__ . '/config.php';
} elseif (!defined('DB_HOST') && file_exists(__DIR__ . '/config.php')) {
require_once __DIR__ . '/config.php';
}
function run_migrations() {
$pdo = db();
$messages = [];
// 1. Create migrations table if not exists
try {
$pdo->exec(
"\n CREATE TABLE IF NOT EXISTS migrations (\n id INT AUTO_INCREMENT PRIMARY KEY,\n migration_name VARCHAR(255) NOT NULL UNIQUE,\n executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n "
);
} catch (PDOException $e) {
return ["Error creating migrations table: " . $e->getMessage()];
}
// 2. Get executed migrations
$executed = [];
try {
$stmt = $pdo->query("SELECT migration_name FROM migrations");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$executed[] = $row['migration_name'];
}
} catch (PDOException $e) {
return ["Error fetching executed migrations: " . $e->getMessage()];
}
// 3. Scan for migration files
$migrationFiles = glob(__DIR__ . '/migrations/*.php');
if ($migrationFiles === false) {
return ["Error scanning migration directory."];
}
// Sort files to ensure order (by name usually works if named correctly)
sort($migrationFiles);
$count = 0;
foreach ($migrationFiles as $file) {
$filename = basename($file);
if (in_array($filename, $executed)) {
continue;
}
// Run migration
try {
// We use output buffering to capture echo output from migration files
ob_start();
// Include inside a closure/function scope to avoid variable collisions
// but we need to ensure $pdo is available if they use it.
// Most files do: require config.php; $pdo = db();
// Since we already required config.php, require_once will skip it.
// So they will just get $pdo = db(); which works.
include $file;
$output = ob_get_clean();
// Log success
$messages[] = "Executed $filename: " . trim($output);
// Record in DB
$stmt = $pdo->prepare("INSERT INTO migrations (migration_name) VALUES (?)");
$stmt->execute([$filename]);
$count++;
} catch (Throwable $e) {
ob_end_clean(); // Clean buffer if error
$messages[] = "Failed to execute $filename: " . $e->getMessage();
return $messages; // Stop on error
}
}
if ($count === 0) {
$messages[] = "No new migrations to run.";
} else {
$messages[] = "Successfully ran $count migrations.";
}
return $messages;
}
// If run directly from CLI
if (php_sapi_name() === 'cli' && basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
$results = run_migrations();
echo implode("\n", $results) . "\n";
}