feature #26859 [Dotenv] add a flag to allow env vars override (fmata)
This PR was merged into the 4.2-dev branch.
Discussion
----------
[Dotenv] add a flag to allow env vars override
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #26846
| License | MIT
| Doc PR | symfony/symfony-docs#9568
I choose to use a new parameter in the constructor instead of `populate()` to not add boilerplate code to them who want allow overriding in their current setup. It's just a parameter to add in `Dotenv` creation instead of change or customize the loading of different .env files.
I targeted 4.1 despite the feature freeze because it's a small change but if you don't agree I can change to 4.2.
~~If you accept this PR I will do the doc PR then.~~
doc ready
Commits
-------
228b220495
[Dotenv] add Dotenv::overload() to allow env vars override
This commit is contained in:
commit
8f5229f768
@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* added `Dotenv::overload()` and `$overrideExistingVars` as optional parameter of `Dotenv::populate()`
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
|
@ -47,25 +47,30 @@ final class Dotenv
|
||||
*/
|
||||
public function load(string $path, string ...$paths): void
|
||||
{
|
||||
array_unshift($paths, $path);
|
||||
$this->doLoad(false, $path, ...$paths);
|
||||
}
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (!is_readable($path) || is_dir($path)) {
|
||||
throw new PathException($path);
|
||||
}
|
||||
|
||||
$this->populate($this->parse(file_get_contents($path), $path));
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @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
|
||||
{
|
||||
$this->doLoad(true, $path, ...$paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets values as environment variables (via putenv, $_ENV, and $_SERVER).
|
||||
*
|
||||
* Note that existing environment variables are not overridden.
|
||||
*
|
||||
* @param array $values An array of env variables
|
||||
* @param array $values An array of env variables
|
||||
* @param bool $overrideExistingVars true when existing environment variables must be overridden
|
||||
*/
|
||||
public function populate(array $values): void
|
||||
public function populate(array $values, bool $overrideExistingVars = false): void
|
||||
{
|
||||
$loadedVars = array_flip(explode(',', getenv('SYMFONY_DOTENV_VARS')));
|
||||
unset($loadedVars['']);
|
||||
@ -73,7 +78,7 @@ final class Dotenv
|
||||
foreach ($values as $name => $value) {
|
||||
$notHttpName = 0 !== strpos($name, 'HTTP_');
|
||||
// don't check existence with getenv() because of thread safety issues
|
||||
if (!isset($loadedVars[$name]) && (isset($_ENV[$name]) || (isset($_SERVER[$name]) && $notHttpName))) {
|
||||
if (!isset($loadedVars[$name]) && (!$overrideExistingVars && (isset($_ENV[$name]) || (isset($_SERVER[$name]) && $notHttpName)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -399,4 +404,17 @@ final class Dotenv
|
||||
{
|
||||
return new FormatException($message, new FormatExceptionContext($this->data, $this->path, $this->lineno, $this->cursor));
|
||||
}
|
||||
|
||||
private function doLoad(bool $overrideExistingVars, string $path, string ...$paths): void
|
||||
{
|
||||
array_unshift($paths, $path);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +186,41 @@ class DotenvTest extends TestCase
|
||||
$this->assertSame('BAZ', $bar);
|
||||
}
|
||||
|
||||
public function testOverload()
|
||||
{
|
||||
unset($_ENV['FOO']);
|
||||
unset($_ENV['BAR']);
|
||||
unset($_SERVER['FOO']);
|
||||
unset($_SERVER['BAR']);
|
||||
|
||||
putenv('FOO=initial_foo_value');
|
||||
putenv('BAR=initial_bar_value');
|
||||
$_ENV['FOO'] = 'initial_foo_value';
|
||||
$_ENV['BAR'] = 'initial_bar_value';
|
||||
|
||||
@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');
|
||||
|
||||
(new DotEnv())->overload($path1, $path2);
|
||||
|
||||
$foo = getenv('FOO');
|
||||
$bar = getenv('BAR');
|
||||
|
||||
putenv('FOO');
|
||||
putenv('BAR');
|
||||
unlink($path1);
|
||||
unlink($path2);
|
||||
rmdir($tmpdir);
|
||||
|
||||
$this->assertSame('BAR', $foo);
|
||||
$this->assertSame('BAZ', $bar);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Dotenv\Exception\PathException
|
||||
*/
|
||||
@ -228,6 +263,18 @@ class DotenvTest extends TestCase
|
||||
$this->assertSame('http_value', $_SERVER['HTTP_TEST_ENV_VAR']);
|
||||
}
|
||||
|
||||
public function testEnvVarIsOverriden()
|
||||
{
|
||||
putenv('TEST_ENV_VAR_OVERRIDEN=original_value');
|
||||
|
||||
$dotenv = new DotEnv();
|
||||
$dotenv->populate(array('TEST_ENV_VAR_OVERRIDEN' => 'new_value'), true);
|
||||
|
||||
$this->assertSame('new_value', getenv('TEST_ENV_VAR_OVERRIDEN'));
|
||||
$this->assertSame('new_value', $_ENV['TEST_ENV_VAR_OVERRIDEN']);
|
||||
$this->assertSame('new_value', $_SERVER['TEST_ENV_VAR_OVERRIDEN']);
|
||||
}
|
||||
|
||||
public function testMemorizingLoadedVarsNamesInSpecialVar()
|
||||
{
|
||||
// Special variable not exists
|
||||
|
Reference in New Issue
Block a user