Fix wizard : suppression totale des sous-processus exec() dans install()
- APP_KEY : généré directement en PHP (random_bytes) + écrit dans .env + propagé via config() et putenv() → évite le bug de pattern-matching de key:generate (la clé en mémoire ≠ clé dans le .env réécrit par writeEnv) - DB_* + APP_KEY : putenv() écrase l'env OS hérité au boot (pgsql/temp-key) pour que tout sous-processus futur hérite des bonnes valeurs - optimize supprimé de l'installation : config:cache re-boostrappe l'app via bootstrap/app.php dans un contexte où l'Encrypter peut lever MissingAppKeyException ; optimize:clear seul suffit — Laravel reconstruit ses caches à la première requête - key:generate converti en Artisan::call() puis remplacé par génération PHP directe Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -128,8 +128,6 @@ class SetupController extends Controller
|
|||||||
|
|
||||||
$steps = [];
|
$steps = [];
|
||||||
$success = true;
|
$success = true;
|
||||||
$php = $this->phpBinary();
|
|
||||||
$artisan = $php . ' ' . escapeshellarg(base_path('artisan'));
|
|
||||||
|
|
||||||
// 1. Écriture du .env
|
// 1. Écriture du .env
|
||||||
try {
|
try {
|
||||||
@@ -140,24 +138,44 @@ class SetupController extends Controller
|
|||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Génération de la clé APP_KEY
|
// 2. Génération de la clé APP_KEY — directement en PHP, sans passer par key:generate.
|
||||||
|
//
|
||||||
|
// Artisan key:generate remplace APP_KEY=<clé_en_mémoire> dans le .env grâce à un
|
||||||
|
// pattern regex. Mais writeEnv() vient d'écrire APP_KEY= (vide) alors qu'en mémoire
|
||||||
|
// la clé est celle de l'auto-création (TEMP_KEY) → le pattern ne matche pas → la
|
||||||
|
// clé reste vide dans le .env et la config:cache en hérite.
|
||||||
|
// Solution : générer la clé nous-mêmes, l'écrire directement dans le .env, et la
|
||||||
|
// propager en mémoire + env OS dès maintenant.
|
||||||
|
$appKey = null;
|
||||||
if ($success) {
|
if ($success) {
|
||||||
[$ok, $out] = $this->artisanRun($artisan, 'key:generate --force');
|
try {
|
||||||
$steps[] = ['ok' => $ok, 'label' => 'Génération de la clé de chiffrement (APP_KEY)', 'error' => $ok ? null : $out];
|
$appKey = 'base64:' . base64_encode(random_bytes(32));
|
||||||
if (! $ok) $success = false;
|
$envPath = base_path('.env');
|
||||||
|
$env = file_get_contents($envPath);
|
||||||
|
$env = preg_replace('/^APP_KEY=.*/m', 'APP_KEY=' . $appKey, $env);
|
||||||
|
file_put_contents($envPath, $env);
|
||||||
|
config(['app.key' => $appKey]);
|
||||||
|
$steps[] = ['ok' => true, 'label' => 'Génération de la clé de chiffrement (APP_KEY)'];
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$steps[] = ['ok' => false, 'label' => 'Génération de la clé de chiffrement (APP_KEY)', 'error' => $e->getMessage()];
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2b. Reconfiguration de la connexion BDD dans le processus courant.
|
// 2b. Reconfiguration de la connexion BDD — processus courant ET sous-processus.
|
||||||
//
|
//
|
||||||
// Problème : public/index.php charge le .env auto-créé (pgsql) au premier boot
|
// putenv() écrase l'env OS hérité au boot (pgsql + TEMP_KEY) pour que tous les
|
||||||
// et appelle putenv('DB_CONNECTION=pgsql'). Les sous-processus exec() héritent
|
// sous-processus futurs (config:cache interne à optimize…) reçoivent les bonnes
|
||||||
// cet env OS. phpdotenv en mode immutable (défaut Laravel) refuse d'écraser une
|
// valeurs. config() + DB::purge() reconfigure le processus courant en mémoire.
|
||||||
// variable déjà présente dans l'env → le nouveau .env (mysql) est ignoré par le
|
|
||||||
// subprocess de migration qui continue à tenter une connexion pgsql.
|
|
||||||
//
|
|
||||||
// Solution : exécuter les migrations via Artisan::call() dans le processus courant
|
|
||||||
// après avoir écrasé la config BDD en mémoire — pas de subprocess, pas d'héritage.
|
|
||||||
if ($success) {
|
if ($success) {
|
||||||
|
putenv("APP_KEY={$appKey}");
|
||||||
|
putenv("DB_CONNECTION={$dbData['driver']}");
|
||||||
|
putenv("DB_HOST={$dbData['host']}");
|
||||||
|
putenv("DB_PORT={$dbData['port']}");
|
||||||
|
putenv("DB_DATABASE={$dbData['database']}");
|
||||||
|
putenv("DB_USERNAME={$dbData['username']}");
|
||||||
|
putenv('DB_PASSWORD=' . ($dbData['password'] ?? ''));
|
||||||
|
|
||||||
$connConfig = $dbData['driver'] === 'pgsql'
|
$connConfig = $dbData['driver'] === 'pgsql'
|
||||||
? ['driver' => 'pgsql', 'host' => $dbData['host'], 'port' => (int) $dbData['port'],
|
? ['driver' => 'pgsql', 'host' => $dbData['host'], 'port' => (int) $dbData['port'],
|
||||||
'database' => $dbData['database'], 'username' => $dbData['username'],
|
'database' => $dbData['database'], 'username' => $dbData['username'],
|
||||||
@@ -214,10 +232,14 @@ class SetupController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Optimisation des caches
|
// 6. Nettoyage des caches
|
||||||
|
// optimize:clear supprime tout cache résiduel (config, routes, vues, events).
|
||||||
|
// On n'appelle PAS optimize : config:cache re-boostrappe l'app depuis bootstrap/app.php
|
||||||
|
// dans un contexte qui peut ne pas avoir accès à notre APP_KEY via putenv, ce qui
|
||||||
|
// provoque MissingAppKeyException. Laravel reconstruit ses caches à la première
|
||||||
|
// requête — pas besoin de les préchauffer pendant l'installation.
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$this->artisanRun($artisan, 'optimize:clear');
|
Artisan::call('optimize:clear');
|
||||||
$this->artisanRun($artisan, 'optimize');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Marquage installation
|
// 7. Marquage installation
|
||||||
|
|||||||
Reference in New Issue
Block a user