Files
PS_Launcher/server/tools/migrate.php
j.foucher 558fa93f2c Add tools/migrate.php — runs SQL migrations from inside OVH infra
OVH shared hosting MySQL hostnames (*.mysql.db) only resolve from inside
OVH's network — phpMyAdmin running locally or any external client gets
"getaddrinfo failed". Either the operator uses OVH-hosted phpMyAdmin (one
click in the manager), or runs SQL through a PHP script that already lives
on the OVH machine.

migrate.php applies every *.sql file in migrations/ in lexicographic order,
using config.php credentials. Works equally from CLI (php tools/migrate.php
in SSH) and from a browser hit one-shot. Statements split on ";\n", skips
SQL comment lines. Idempotent thanks to CREATE TABLE IF NOT EXISTS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 10:55:18 +02:00

95 lines
2.8 KiB
PHP

<?php
/**
* Mini script de migration : applique tous les fichiers SQL présents dans
* migrations/ sur la base configurée dans api/config.php.
*
* Utilisable de deux façons :
* 1. En SSH : cd ~/www/PS_Launcher && php tools/migrate.php
* 2. Via le navigateur : https://asterionvr.com/PS_Launcher/tools/migrate.php
* (à supprimer après la première migration pour ne pas l'exposer)
*
* Le script est idempotent : les CREATE TABLE IF NOT EXISTS ne ré-écrasent pas
* les tables existantes. Tu peux donc le rejouer sans risque.
*/
declare(strict_types=1);
// Sécurité minimale : refuse l'exécution web si la config n'est pas là
$configPath = dirname(__DIR__) . '/api/config.php';
if (!is_file($configPath)) {
http_response_code(500);
header('Content-Type: text/plain; charset=utf-8');
echo "Erreur : api/config.php absent.\n";
exit(1);
}
$config = require $configPath;
// Mode CLI ou web ?
$cli = (PHP_SAPI === 'cli');
if (!$cli) {
header('Content-Type: text/plain; charset=utf-8');
}
function out(string $line): void {
echo $line . "\n";
if (PHP_SAPI !== 'cli') @ob_flush();
@flush();
}
out("=== PS_Launcher migrate.php ===");
out("DSN: " . $config['db']['dsn']);
try {
$pdo = new PDO(
$config['db']['dsn'],
$config['db']['username'],
$config['db']['password'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
out("Connexion DB OK");
} catch (Exception $e) {
out("ÉCHEC connexion : " . $e->getMessage());
exit(2);
}
$migrationsDir = dirname(__DIR__) . '/migrations';
$files = glob("$migrationsDir/*.sql") ?: [];
sort($files);
if (!$files) {
out("Aucun fichier SQL dans $migrationsDir");
exit(0);
}
foreach ($files as $f) {
out("");
out("--- " . basename($f) . " ---");
$sql = file_get_contents($f);
// Découpe naïve sur les ';' suivis d'un saut de ligne (suffit pour notre schéma)
$statements = array_filter(array_map('trim', preg_split('/;\s*\n/', $sql) ?: []));
foreach ($statements as $stmt) {
if ($stmt === '' || str_starts_with($stmt, '--')) continue;
try {
$pdo->exec($stmt);
$first40 = substr(preg_replace('/\s+/', ' ', $stmt), 0, 60);
out("" . $first40 . "");
} catch (Exception $e) {
out(" ✘ ERREUR : " . $e->getMessage());
out(" Sur : " . substr($stmt, 0, 80) . "");
exit(3);
}
}
}
out("");
out("=== Migration terminée. Tables présentes ===");
$tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $t) out(" - $t");
if (!$cli) {
out("");
out("⚠ Pour la sécurité, supprime maintenant tools/migrate.php du serveur.");
}