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

Skip to content

[DotEnv] Add a new loadForEnv() method mimicking Ruby's dotenv behavior #28533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 42 additions & 15 deletions src/Symfony/Component/Dotenv/Dotenv.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* Manages .env files.
*
* @author Fabien Potencier <[email protected]>
* @author Kévin Dunglas <[email protected]>
*/
final class Dotenv
{
Expand All @@ -39,29 +40,57 @@ final class Dotenv
/**
* Loads one or several .env files.
*
* @param string $path A file to load
* @param ...string $paths A list of additional files to load
* @param string $path A file to load
* @param ...string $extraPaths A list of additional files to load
*
* @throws FormatException when a file has a syntax error
* @throws PathException when a file does not exist or is not readable
*/
public function load(string $path, string ...$paths): void
public function load(string $path, string ...$extraPaths): void
{
$this->doLoad(false, $path, $paths);
$this->doLoad(false, false, \func_get_args());
}

/**
* Loads one or several .env and the corresponding env.$env, env.local and env.$env.local files if they exist.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to be missing the dots in front of the files like .env.$env

*
* .env.local is always ignored in test env because tests should produce the same results for everyone.
*
* @param string $path A file to load
* @param ...string $extraPaths A list of additional files to load
*
* @throws FormatException when a file has a syntax error
* @throws PathException when a file does not exist or is not readable
*
* @see https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
*/
public function loadForEnv(string $env, string $path, string ...$extraPaths): void
{
$paths = \func_get_args();
for ($i = 1; $i < \func_num_args(); ++$i) {
$path = $paths[$i];
$pathList = array($path, "$path.$env");
if ('test' !== $env) {
$pathList[] = "$path.local";
}
$pathList[] = "$path.$env.local";

$this->doLoad(false, true, $pathList);
}
}

/**
* Loads one or several .env files and enables override existing vars.
*
* @param string $path A file to load
* @param ...string $paths A list of additional files to load
* @param string $path A file to load
* @param ...string $extraPaths A list of additional files to load
*
* @throws FormatException when a file has a syntax error
* @throws PathException when a file does not exist or is not readable
*/
public function overload(string $path, string ...$paths): void
public function overload(string $path, string ...$extraPaths): void
{
$this->doLoad(true, $path, $paths);
$this->doLoad(true, false, \func_get_args());
}

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

private function doLoad(bool $overrideExistingVars, string $path, array $paths): void
private function doLoad(bool $overrideExistingVars, bool $ignoreMissingExtraPaths, array $paths): void
{
array_unshift($paths, $path);

foreach ($paths as $path) {
if (!is_readable($path) || is_dir($path)) {
foreach ($paths as $i => $path) {
if (is_readable($path) && !is_dir($path)) {
$this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars);
} elseif (!$ignoreMissingExtraPaths || 0 === $i) {
throw new PathException($path);
}

$this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars);
}
}
}
58 changes: 58 additions & 0 deletions src/Symfony/Component/Dotenv/Tests/DotenvTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,64 @@ public function testLoad()
$this->assertSame('BAZ', $bar);
}

public function testLoadForEnv()
{
unset($_ENV['FOO']);
unset($_ENV['BAR']);
unset($_SERVER['FOO']);
unset($_SERVER['BAR']);
putenv('FOO');
putenv('BAR');

@mkdir($tmpdir = sys_get_temp_dir().'/dotenv');

$path1 = tempnam($tmpdir, 'sf-');
$path2 = tempnam($tmpdir, 'sf-');

file_put_contents($path1, 'FOO=BAR');
file_put_contents($path2, 'BAR=BAZ');

// .env

(new DotEnv())->loadForEnv('dev', $path1, $path2);

$this->assertSame('BAR', getenv('FOO'));
$this->assertSame('BAZ', getenv('BAR'));

// .env.dev

file_put_contents("$path1.dev", 'FOO=devBAR');
(new DotEnv())->loadForEnv('dev', $path1, $path2);
$this->assertSame('devBAR', getenv('FOO'));

// .env.local

file_put_contents("$path1.local", 'FOO=localBAR');
(new DotEnv())->loadForEnv('dev', $path1, $path2);
$this->assertSame('localBAR', getenv('FOO'));

// special case for test

file_put_contents("$path1.local", 'FOO=testBAR');
(new DotEnv())->loadForEnv('test', $path1, $path2);
$this->assertSame('BAR', getenv('FOO'));

// .env.dev.local

file_put_contents("$path1.dev.local", 'FOO=devlocalBAR');
(new DotEnv())->loadForEnv('dev', $path1, $path2);
$this->assertSame('devlocalBAR', getenv('FOO'));

putenv('FOO');
putenv('BAR');
unlink($path1);
unlink("$path1.dev");
unlink("$path1.local");
unlink("$path1.dev.local");
unlink($path2);
rmdir($tmpdir);
}

public function testOverload()
{
unset($_ENV['FOO']);
Expand Down