Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1000890

Browse files
committed
[DotEnv] Add a new loadForEnv() method mimicking Ruby's dotenv behavior
1 parent bf4d011 commit 1000890

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

src/Symfony/Component/Dotenv/Dotenv.php

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* Manages .env files.
2222
*
2323
* @author Fabien Potencier <[email protected]>
24+
* @author Kévin Dunglas <[email protected]>
2425
*/
2526
final class Dotenv
2627
{
@@ -50,6 +51,32 @@ public function load(string $path, string ...$paths): void
5051
$this->doLoad(false, $path, $paths);
5152
}
5253

54+
/**
55+
* Loads one or several .env and the corresponding env.local, env.$env and env.$env.local files if they exist.
56+
*
57+
* The env.test.local is always ignored because tests should produce the same results for everyone.
58+
*
59+
* @param string $path A file to load
60+
* @param ...string $paths A list of additional files to load
61+
*
62+
* @throws FormatException when a file has a syntax error
63+
* @throws PathException when a file does not exist or is not readable
64+
*
65+
* @see https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
66+
*/
67+
public function loadForEnv(string $env, string $path, string ...$paths): void
68+
{
69+
array_unshift($paths, $path);
70+
foreach ($paths as $p) {
71+
$pathList = ["$p.$env"];
72+
if ($env !== 'test') {
73+
$pathList[] = "$p.local";
74+
}
75+
$pathList[] = "$p.$env.local";
76+
77+
$this->doLoad(false, $p, $pathList, true);
78+
}
79+
}
5380
/**
5481
* Loads one or several .env files and enables override existing vars.
5582
*
@@ -405,16 +432,24 @@ private function createFormatException($message)
405432
return new FormatException($message, new FormatExceptionContext($this->data, $this->path, $this->lineno, $this->cursor));
406433
}
407434

408-
private function doLoad(bool $overrideExistingVars, string $path, array $paths): void
435+
/**
436+
* @param bool $envMode Silently ignore not existing files in $paths (but not the one in $path)
437+
*/
438+
private function doLoad(bool $overrideExistingVars, string $path, array $paths, bool $envMode = false): void
409439
{
410440
array_unshift($paths, $path);
411441

442+
$silent = false;
412443
foreach ($paths as $path) {
413444
if (!is_readable($path) || is_dir($path)) {
445+
if ($silent) {
446+
continue;
447+
}
414448
throw new PathException($path);
415449
}
416450

417451
$this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars);
452+
$silent = $envMode;
418453
}
419454
}
420455
}

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,64 @@ public function testLoad()
186186
$this->assertSame('BAZ', $bar);
187187
}
188188

189+
public function testLoadForEnv()
190+
{
191+
unset($_ENV['FOO']);
192+
unset($_ENV['BAR']);
193+
unset($_SERVER['FOO']);
194+
unset($_SERVER['BAR']);
195+
putenv('FOO');
196+
putenv('BAR');
197+
198+
@mkdir($tmpdir = sys_get_temp_dir().'/dotenv');
199+
200+
$path1 = tempnam($tmpdir, 'sf-');
201+
$path2 = tempnam($tmpdir, 'sf-');
202+
203+
file_put_contents($path1, 'FOO=BAR');
204+
file_put_contents($path2, 'BAR=BAZ');
205+
206+
// .env
207+
208+
(new DotEnv())->loadForEnv('dev', $path1, $path2);
209+
210+
$this->assertSame('BAR', getenv('FOO'));
211+
$this->assertSame('BAZ', getenv('BAR'));
212+
213+
// .env.dev
214+
215+
file_put_contents("$path1.dev", 'FOO=devBAR');
216+
(new DotEnv())->loadForEnv('dev', $path1, $path2);
217+
$this->assertSame('devBAR', getenv('FOO'));
218+
219+
// .env.local
220+
221+
file_put_contents("$path1.local", 'FOO=localBAR');
222+
(new DotEnv())->loadForEnv('dev', $path1, $path2);
223+
$this->assertSame('localBAR', getenv('FOO'));
224+
225+
// special case for test
226+
227+
file_put_contents("$path1.local", 'FOO=testBAR');
228+
(new DotEnv())->loadForEnv('test', $path1, $path2);
229+
$this->assertSame('BAR', getenv('FOO'));
230+
231+
// .env.dev.local
232+
233+
file_put_contents("$path1.dev.local", 'FOO=devlocalBAR');
234+
(new DotEnv())->loadForEnv('dev', $path1, $path2);
235+
$this->assertSame('devlocalBAR', getenv('FOO'));
236+
237+
putenv('FOO');
238+
putenv('BAR');
239+
unlink($path1);
240+
unlink("$path1.dev");
241+
unlink("$path1.local");
242+
unlink("$path1.dev.local");
243+
unlink($path2);
244+
rmdir($tmpdir);
245+
}
246+
189247
public function testOverload()
190248
{
191249
unset($_ENV['FOO']);

0 commit comments

Comments
 (0)