Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fefb2ff

Browse filesBrowse files
bug #32943 [Dotenv] search variable values in ENV first then env file (soufianZantar)
This PR was merged into the 3.4 branch. Discussion ---------- [Dotenv] search variable values in ENV first then env file | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no <!-- please update src/**/CHANGELOG.md files --> | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | #32595 | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> <!-- Replace this notice by a short README for your feature/bugfix. This will help people understand your PR and can be used as a start for the documentation. Additionally (see https://symfony.com/roadmap): - Bug fixes must be submitted against the lowest maintained branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too). - Features and deprecations must be submitted against branch 4.4. - Legacy code removals go to the master branch. --> I think we must searhing the value of variables in $_ENV before the .env file to fix this issues. before this fix Parse method will return the value in .env file and not the value passed in this command `composer dump-env prod `. **the issue:** In my .env file, I have a variable TEST that depends on the APP_ENV variable like this: ``` # .env file ###> symfony/framework-bundle ### APP_ENV=dev APP_SECRET=2eb810c79fba0dd5c029a2fa53bfdb51 ###< symfony/framework-bundle ### TEST=foo_${APP_ENV} ``` I run composer dump-env dev command to generate my .env.locale.php, everything works fine, the value of my variable TEST is correct. ``` // .env.locale.php return array ( 'APP_ENV' => 'dev', 'TEST' => 'foo_dev', 'APP_SECRET' => '2eb810c79fba0dd5c029a2fa53bfdb51', ); ``` Then I run the same command with prod environment (composer dump-env prod), the value of TEST is wrong (it is same as for dev) ``` // .env.locale.php return array ( 'APP_ENV' => 'prod', 'TEST' => 'foo_dev', 'APP_SECRET' => '2eb810c79fba0dd5c029a2fa53bfdb51', ); ``` Commits ------- 3018041 [Dotenv] search variable values in ENV first then env file
2 parents 49ad46e + 3018041 commit fefb2ff
Copy full SHA for fefb2ff

File tree

Expand file treeCollapse file tree

3 files changed

+43
-14
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+43
-14
lines changed

‎src/Symfony/Component/Dotenv/Dotenv.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Dotenv/Dotenv.php
+25-13Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ private function lexValue()
183183
throw $this->createFormatException('Whitespace are not supported before the value');
184184
}
185185

186+
$loadedVars = array_flip(explode(',', isset($_SERVER['SYMFONY_DOTENV_VARS']) ? $_SERVER['SYMFONY_DOTENV_VARS'] : (isset($_ENV['SYMFONY_DOTENV_VARS']) ? $_ENV['SYMFONY_DOTENV_VARS'] : '')));
187+
unset($loadedVars['']);
186188
$v = '';
187189

188190
do {
@@ -224,8 +226,8 @@ private function lexValue()
224226
++$this->cursor;
225227
$value = str_replace(['\\"', '\r', '\n'], ['"', "\r", "\n"], $value);
226228
$resolvedValue = $value;
227-
$resolvedValue = $this->resolveVariables($resolvedValue);
228-
$resolvedValue = $this->resolveCommands($resolvedValue);
229+
$resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars);
230+
$resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars);
229231
$resolvedValue = str_replace('\\\\', '\\', $resolvedValue);
230232
$v .= $resolvedValue;
231233
} else {
@@ -247,8 +249,8 @@ private function lexValue()
247249
}
248250
$value = rtrim($value);
249251
$resolvedValue = $value;
250-
$resolvedValue = $this->resolveVariables($resolvedValue);
251-
$resolvedValue = $this->resolveCommands($resolvedValue);
252+
$resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars);
253+
$resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars);
252254
$resolvedValue = str_replace('\\\\', '\\', $resolvedValue);
253255

254256
if ($resolvedValue === $value && preg_match('/\s+/', $value)) {
@@ -301,7 +303,7 @@ private function skipEmptyLines()
301303
}
302304
}
303305

304-
private function resolveCommands($value)
306+
private function resolveCommands($value, $loadedVars)
305307
{
306308
if (false === strpos($value, '$')) {
307309
return $value;
@@ -317,7 +319,7 @@ private function resolveCommands($value)
317319
)
318320
/x';
319321

320-
return preg_replace_callback($regex, function ($matches) {
322+
return preg_replace_callback($regex, function ($matches) use ($loadedVars) {
321323
if ('\\' === $matches[1]) {
322324
return substr($matches[0], 1);
323325
}
@@ -332,7 +334,15 @@ private function resolveCommands($value)
332334

333335
$process = new Process('echo '.$matches[0]);
334336
$process->inheritEnvironmentVariables(true);
335-
$process->setEnv($this->values);
337+
338+
$env = [];
339+
foreach ($this->values as $name => $value) {
340+
if (isset($loadedVars[$name]) || (!isset($_ENV[$name]) && !(isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')))) {
341+
$env[$name] = $value;
342+
}
343+
}
344+
$process->setEnv($env);
345+
336346
try {
337347
$process->mustRun();
338348
} catch (ProcessException $e) {
@@ -343,7 +353,7 @@ private function resolveCommands($value)
343353
}, $value);
344354
}
345355

346-
private function resolveVariables($value)
356+
private function resolveVariables($value, array $loadedVars)
347357
{
348358
if (false === strpos($value, '$')) {
349359
return $value;
@@ -359,7 +369,7 @@ private function resolveVariables($value)
359369
(?P<closing_brace>\})? # optional closing brace
360370
/x';
361371

362-
$value = preg_replace_callback($regex, function ($matches) {
372+
$value = preg_replace_callback($regex, function ($matches) use ($loadedVars) {
363373
// odd number of backslashes means the $ character is escaped
364374
if (1 === \strlen($matches['backslashes']) % 2) {
365375
return substr($matches[0], 1);
@@ -375,14 +385,16 @@ private function resolveVariables($value)
375385
}
376386

377387
$name = $matches['name'];
378-
if (isset($this->values[$name])) {
388+
if (isset($loadedVars[$name]) && isset($this->values[$name])) {
379389
$value = $this->values[$name];
380-
} elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
381-
$value = $_SERVER[$name];
382390
} elseif (isset($_ENV[$name])) {
383391
$value = $_ENV[$name];
392+
} elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
393+
$value = $_SERVER[$name];
394+
} elseif (isset($this->values[$name])) {
395+
$value = $this->values[$name];
384396
} else {
385-
$value = (string) getenv($name);
397+
$value = '';
386398
}
387399

388400
if (!$matches['opening_brace'] && isset($matches['closing_brace'])) {

‎src/Symfony/Component/Dotenv/Tests/DotenvTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Dotenv/Tests/DotenvTest.php
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public function testParse($data, $expected)
6363
public function getEnvData()
6464
{
6565
putenv('LOCAL=local');
66+
$_ENV['LOCAL'] = 'local';
6667
$_ENV['REMOTE'] = 'remote';
6768

6869
$tests = [
@@ -295,4 +296,20 @@ public function testOverridingEnvVarsWithNamesMemorizedInSpecialVar()
295296
$this->assertSame('baz1', getenv('BAZ'));
296297
$this->assertSame('/var/www', getenv('DOCUMENT_ROOT'));
297298
}
299+
300+
public function testGetVariablesValueFromEnvFirst()
301+
{
302+
$_ENV['APP_ENV'] = 'prod';
303+
$dotenv = new Dotenv(true);
304+
305+
$test = "APP_ENV=dev\nTEST1=foo1_\${APP_ENV}";
306+
$values = $dotenv->parse($test);
307+
$this->assertSame('foo1_prod', $values['TEST1']);
308+
309+
if ('\\' !== \DIRECTORY_SEPARATOR) {
310+
$test = "APP_ENV=dev\nTEST2=foo2_\$(php -r 'echo \$_SERVER[\"APP_ENV\"];')";
311+
$values = $dotenv->parse($test);
312+
$this->assertSame('foo2_prod', $values['TEST2']);
313+
}
314+
}
298315
}

‎src/Symfony/Component/Dotenv/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/Dotenv/composer.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"php": "^5.5.9|>=7.0.8"
2020
},
2121
"require-dev": {
22-
"symfony/process": "~3.2|~4.0"
22+
"symfony/process": "^3.4.2|^4.0"
2323
},
2424
"autoload": {
2525
"psr-4": { "Symfony\\Component\\Dotenv\\": "" },

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.