From ed412739fe3aef7d46dee6cac379e181d3b9ba42 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 14 Nov 2025 18:57:56 +0100 Subject: [PATCH] Fix dump-env command when .env files reference other env vars --- src/Command/DumpEnvCommand.php | 24 ++++++++++++ tests/Command/DumpEnvCommandTest.php | 57 ++++++++++++++++++++++------ 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/Command/DumpEnvCommand.php b/src/Command/DumpEnvCommand.php index 7b109dcf..0a99dcc1 100644 --- a/src/Command/DumpEnvCommand.php +++ b/src/Command/DumpEnvCommand.php @@ -55,6 +55,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $path = $this->options->get('root-dir').'/'.($runtime['dotenv_path'] ?? '.env'); + $GLOBALS['SYMFONY_DOTENV_VARS'] = []; if (!$env || !$input->getOption('empty')) { $vars = $this->loadEnv($path, $env, $runtime); @@ -66,6 +67,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $vars = var_export($vars, true); + + foreach ($GLOBALS['SYMFONY_DOTENV_VARS'] as $k => $v) { + $k = var_export($k, true); + $vars = str_replace($v, "'.(\$_ENV[{$k}] ?? ".(str_starts_with($k, "'HTTP_") ? '' : "\$_SERVER[{$k}] ?? ")."'').'", $vars); + } + unset($GLOBALS['SYMFONY_DOTENV_VARS']); + $vars = strtr($vars, [ + "''.(" => '(', + ").''.(" => ').(', + ").''" => ')', + ]); + $vars = <<createCommandDumpEnv(); @@ -60,9 +60,9 @@ public function testEmptyOptionMustIgnoreContent() @unlink($envLocal); $envContent = <<createCommandDumpEnv(); @@ -94,9 +94,9 @@ public function testEnvCanBeReferenced() @unlink($envLocal); $envContent = <<<'EOF' -BAR=$FOO -FOO=123 -EOF; + BAR=$FOO + FOO=123 + EOF; file_put_contents($env, $envContent); $_SERVER['FOO'] = 'Foo'; @@ -179,9 +179,9 @@ public function testLoadLocalEnvWhenTestEnvIsNotEqual() file_put_contents($env, 'APP_ENV=dev'); file_put_contents($envLocal, <<createCommandDumpEnv(['runtime' => ['test_envs' => []]]); @@ -202,6 +202,39 @@ public function testLoadLocalEnvWhenTestEnvIsNotEqual() unlink($envLocalPhp); } + public function testEnvVarReferenceInDumpedFile() + { + @mkdir(FLEX_TEST_DIR); + $env = FLEX_TEST_DIR.'/.env'; + $envLocal = FLEX_TEST_DIR.'/.env.local.php'; + + @unlink($env); + @unlink($envLocal); + + $envContent = <<<'EOF' + APP_ENV=prod + APP_SHARE_DIR=$APP_PROJECT_DIR/var/share + EOF; + file_put_contents($env, $envContent); + + $command = $this->createCommandDumpEnv(); + $command->execute(['env' => 'prod']); + + $dumpedContent = file_get_contents($envLocal); + $this->assertStringContainsString("\$_ENV['APP_PROJECT_DIR']", $dumpedContent); + $this->assertStringContainsString("\$_SERVER['APP_PROJECT_DIR']", $dumpedContent); + + $_ENV['APP_PROJECT_DIR'] = '/path/to/project'; + $vars = require $envLocal; + $this->assertSame([ + 'APP_ENV' => 'prod', + 'APP_SHARE_DIR' => '/path/to/project/var/share', + ], $vars); + + unlink($env); + unlink($envLocal); + } + private function createCommandDumpEnv(array $options = []) { $command = new DumpEnvCommand(