Complete Phase 1: MVC, DB migrations, Auth, RBAC, Security, and Views
This commit is contained in:
105
app/Services/Database/MigrationRunner.php
Normal file
105
app/Services/Database/MigrationRunner.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?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]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user