93 lines
3.2 KiB
PHP
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";
|
|
}
|