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

Skip to content

Commit 774a78c

Browse files
dunglasnicolas-grekas
authored andcommitted
[DotEnv] Add a new loadForEnv() method mimicking Ruby's dotenv behavior
1 parent 07c46a2 commit 774a78c

File tree

2 files changed

+100
-15
lines changed

2 files changed

+100
-15
lines changed

src/Symfony/Component/Dotenv/Dotenv.php

Lines changed: 42 additions & 15 deletions
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
{
@@ -39,29 +40,57 @@ final class Dotenv
3940
/**
4041
* Loads one or several .env files.
4142
*
42-
* @param string $path A file to load
43-
* @param ...string $paths A list of additional files to load
43+
* @param string $path A file to load
44+
* @param ...string $extraPaths A list of additional files to load
4445
*
4546
* @throws FormatException when a file has a syntax error
4647
* @throws PathException when a file does not exist or is not readable
4748
*/
48-
public function load(string $path, string ...$paths): void
49+
public function load(string $path, string ...$extraPaths): void
4950
{
50-
$this->doLoad(false, $path, $paths);
51+
$this->doLoad(false, false, \func_get_args());
52+
}
53+
54+
/**
55+
* Loads one or several .env and the corresponding env.$env, env.local and env.$env.local files if they exist.
56+
*
57+
* .env.local is always ignored in test env because tests should produce the same results for everyone.
58+
*
59+
* @param string $path A file to load
60+
* @param ...string $extraPaths 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 ...$extraPaths): void
68+
{
69+
$paths = \func_get_args();
70+
for ($i = 1; $i < \func_num_args(); ++$i) {
71+
$path = $paths[$i];
72+
$pathList = array($path, "$path.$env");
73+
if ('test' !== $env) {
74+
$pathList[] = "$path.local";
75+
}
76+
$pathList[] = "$path.$env.local";
77+
78+
$this->doLoad(false, true, $pathList);
79+
}
5180
}
5281

5382
/**
5483
* Loads one or several .env files and enables override existing vars.
5584
*
56-
* @param string $path A file to load
57-
* @param ...string $paths A list of additional files to load
85+
* @param string $path A file to load
86+
* @param ...string $extraPaths A list of additional files to load
5887
*
5988
* @throws FormatException when a file has a syntax error
6089
* @throws PathException when a file does not exist or is not readable
6190
*/
62-
public function overload(string $path, string ...$paths): void
91+
public function overload(string $path, string ...$extraPaths): void
6392
{
64-
$this->doLoad(true, $path, $paths);
93+
$this->doLoad(true, false, \func_get_args());
6594
}
6695

6796
/**
@@ -405,16 +434,14 @@ private function createFormatException($message)
405434
return new FormatException($message, new FormatExceptionContext($this->data, $this->path, $this->lineno, $this->cursor));
406435
}
407436

408-
private function doLoad(bool $overrideExistingVars, string $path, array $paths): void
437+
private function doLoad(bool $overrideExistingVars, bool $ignoreMissingExtraPaths, array $paths): void
409438
{
410-
array_unshift($paths, $path);
411-
412-
foreach ($paths as $path) {
413-
if (!is_readable($path) || is_dir($path)) {
439+
foreach ($paths as $i => $path) {
440+
if (is_readable($path) && !is_dir($path)) {
441+
$this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars);
442+
} elseif (!$ignoreMissingExtraPaths || 0 === $i) {
414443
throw new PathException($path);
415444
}
416-
417-
$this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars);
418445
}
419446
}
420447
}

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)