execute(" CREATE TABLE IF NOT EXISTS migrations ( id INT AUTO_INCREMENT PRIMARY KEY, filename VARCHAR(255) NOT NULL UNIQUE, executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, KEY idx_filename (filename) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 "); echo "✅ Tabla de control de migraciones verificada\n"; // Obtener lista de migraciones ejecutadas $executed = $db->fetchAll("SELECT filename FROM migrations"); $executedFiles = array_column($executed, 'filename'); // Buscar archivos .sql en database/ Y en migrations/ (carpeta raíz del proyecto) $dbFiles = glob(__DIR__ . '/*.sql') ?: []; $migrationsFiles = glob(__DIR__ . '/../migrations/*.sql') ?: []; // Unir y ordenar por nombre de archivo (orden cronológico por prefijo) $allFiles = array_unique(array_merge($dbFiles, $migrationsFiles)); usort($allFiles, fn($a, $b) => strcmp(basename($a), basename($b))); $migrationFiles = $allFiles; if (empty($migrationFiles)) { echo "ℹ️ No se encontraron archivos de migración\n"; exit(0); } echo "📋 Encontrados " . count($migrationFiles) . " archivos de migración\n"; echo " (database/: " . count($dbFiles) . ", migrations/: " . count($migrationsFiles) . ")\n\n"; $executed_count = 0; $skipped_count = 0; foreach ($migrationFiles as $file) { $filename = basename($file); // Saltar archivo de backup completo if (strpos($filename, 'backup') !== false) { continue; } // Verificar si ya fue ejecutada if (in_array($filename, $executedFiles)) { echo "⏭️ Saltando $filename (ya ejecutada)\n"; $skipped_count++; continue; } echo "🔄 Ejecutando migración: $filename\n"; try { $sql = file_get_contents($file); // Dividir en sentencias individuales $statements = array_filter(array_map('trim', explode(';', $sql))); $stmt_count = 0; foreach ($statements as $stmt) { // Saltar comentarios y líneas vacías if (empty($stmt) || preg_match('/^--/', $stmt)) { continue; } try { $db->execute($stmt); $stmt_count++; } catch (Exception $e) { // Ignorar errores de "ya existe" (IF NOT EXISTS) if (strpos($e->getMessage(), 'Duplicate column') !== false || strpos($e->getMessage(), 'already exists') !== false) { // Columna ya existe, no es un error real continue; } throw $e; } } // Registrar migración como ejecutada $db->execute( "INSERT INTO migrations (filename) VALUES (?)", [$filename] ); echo " ✓ Ejecutadas $stmt_count sentencias SQL\n"; $executed_count++; } catch (Exception $e) { echo " ✗ Error en $filename: " . $e->getMessage() . "\n"; // Continuar con la siguiente migración } } echo "\n"; echo "═══════════════════════════════════════════\n"; echo "✅ Migraciones completadas\n"; echo " - Ejecutadas: $executed_count\n"; echo " - Saltadas: $skipped_count\n"; echo "═══════════════════════════════════════════\n"; } catch (Exception $e) { echo "❌ Error fatal en sistema de migraciones: " . $e->getMessage() . "\n"; exit(1); } exit(0);