Files
scoutiq/app/Services/Database/MigrationRunner.php

106 lines
2.7 KiB
PHP

<?php
namespace App\Services\Database;
use PDO;
class MigrationRunner
{
private PDO $pdo;
private string $migrationsDir;
public function __construct(Connection $connection)
{
$this->pdo = $connection->getPdo();
$this->migrationsDir = __DIR__ . '/../../../database/migrations';
}
/**
* Run all pending migrations.
*/
public function migrate(): void
{
$this->createMigrationsTable();
$executed = $this->getExecutedMigrations();
if (!is_dir($this->migrationsDir)) {
mkdir($this->migrationsDir, 0755, true);
}
$files = glob($this->migrationsDir . '/*.sql');
if ($files === false) {
$files = [];
}
sort($files);
$count = 0;
foreach ($files as $file) {
$name = basename($file);
if (!in_array($name, $executed)) {
echo "Running migration: {$name}...\n";
$this->executeSqlFile($file);
$this->logMigration($name);
echo "Successfully ran: {$name}\n";
$count++;
}
}
if ($count === 0) {
echo "Nothing to migrate. Database is up to date!\n";
}
}
/**
* Create the tracking migrations table if it does not exist.
*/
private function createMigrationsTable(): void
{
$sql = "CREATE TABLE IF NOT EXISTS migrations (
id INT AUTO_INCREMENT PRIMARY KEY,
migration VARCHAR(255) NOT NULL,
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
$this->pdo->exec($sql);
}
/**
* Get list of already executed migrations.
*/
private function getExecutedMigrations(): array
{
$stmt = $this->pdo->query("SELECT migration FROM migrations");
$results = $stmt->fetchAll(PDO::FETCH_COLUMN);
return $results ?: [];
}
/**
* Execute SQL file.
*/
private function executeSqlFile(string $filePath): void
{
$sql = file_get_contents($filePath);
if (!$sql) {
return;
}
try {
// Run SQL commands
$this->pdo->exec($sql);
} catch (\PDOException $e) {
echo "Error running migration from file: " . basename($filePath) . "\n";
echo "Details: " . $e->getMessage() . "\n";
throw $e;
}
}
/**
* Log executed migration.
*/
private function logMigration(string $name): void
{
$stmt = $this->pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
$stmt->execute([$name]);
}
}