diff --git a/src/Symfony/Component/Dotenv/CHANGELOG.md b/src/Symfony/Component/Dotenv/CHANGELOG.md index 2204282c26ca6..3af8c85639b34 100644 --- a/src/Symfony/Component/Dotenv/CHANGELOG.md +++ b/src/Symfony/Component/Dotenv/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added support for overriding existing envs + 3.3.0 ----- diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 2e907b8c980b8..acd3199e50144 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -48,26 +48,34 @@ final class Dotenv public function load($path/*, ...$paths*/) { // func_get_args() to be replaced by a variadic argument for Symfony 4.0 - foreach (func_get_args() as $path) { - if (!is_readable($path) || is_dir($path)) { - throw new PathException($path); - } + $this->doLoad(func_get_args(), false); + } - $this->populate($this->parse(file_get_contents($path), $path)); - } + /** + * Loads one or several .env files with overriding existing vars. + * + * @param string $path A file to load + * @param ...string $paths 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($path/*, ...$paths*/) + { + // func_get_args() to be replaced by a variadic argument for Symfony 4.0 + $this->doLoad(func_get_args(), true); } /** * Sets values as environment variables (via putenv, $_ENV, and $_SERVER). * - * Note that existing environment variables are never overridden. - * - * @param array $values An array of env variables + * @param array $values An array of env variables + * @param bool $overrideExistingVars Override the existing env variables */ - public function populate($values) + public function populate($values, $overrideExistingVars = false) { foreach ($values as $name => $value) { - if (isset($_ENV[$name]) || isset($_SERVER[$name]) || false !== getenv($name)) { + if (!$overrideExistingVars && (isset($_ENV[$name]) || isset($_SERVER[$name]) || false !== getenv($name))) { continue; } @@ -374,4 +382,15 @@ private function createFormatException($message) { return new FormatException($message, new FormatExceptionContext($this->data, $this->path, $this->lineno, $this->cursor)); } + + private function doLoad(array $paths, $overrideExistingVars = false) + { + foreach ($paths as $path) { + if (!is_readable($path) || is_dir($path)) { + throw new PathException($path); + } + + $this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars); + } + } } diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index 47598030a87f1..b65aa73ce2a3e 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -186,6 +186,38 @@ public function testLoad() $this->assertSame('BAZ', $bar); } + public function testOverload() + { + unset($_ENV['FOO']); + unset($_SERVER['FOO']); + putenv('FOO'); + $_ENV['BAR'] = 'BAR'; + $_SERVER['BAR'] = 'BAR'; + putenv('BAR=BAR'); + + @mkdir($tmpdir = sys_get_temp_dir().'/dotenv'); + + $path1 = tempnam($tmpdir, 'sf-'); + $path2 = tempnam($tmpdir, 'sf-'); + + file_put_contents($path1, 'FOO=FOO'); + file_put_contents($path2, 'BAR=BAZ'); + + (new DotEnv())->overload($path1, $path2); + + $foo = getenv('FOO'); + $bar = getenv('BAR'); + + putenv('FOO'); + putenv('BAR'); + unlink($path1); + unlink($path2); + rmdir($tmpdir); + + $this->assertSame('FOO', $foo); + $this->assertSame('BAZ', $bar); + } + /** * @expectedException \Symfony\Component\Dotenv\Exception\PathException */ @@ -214,4 +246,14 @@ public function testEnvVarIsNotOverriden() $this->assertSame('original_value', getenv('TEST_ENV_VAR')); } + + public function testOverrideEnvVar() + { + putenv('TEST_ENV_VAR=original_value'); + + $dotenv = new DotEnv(); + $dotenv->populate(array('TEST_ENV_VAR' => 'new_value'), true); + + $this->assertSame('new_value', getenv('TEST_ENV_VAR')); + } }