8000 [Dotenv] load .env.local.php and define APP_DEBUG · symfony/symfony@e44c3a7 · GitHub
[go: up one dir, main page]

Skip to content

Commit e44c3a7

Browse files
[Dotenv] load .env.local.php and define APP_DEBUG
1 parent 37a8863 commit e44c3a7

File tree

5 files changed

+102
-36
lines changed

5 files changed

+102
-36
lines changed

UPGRADE-5.1.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
UPGRADE FROM 5.0 to 5.1
22
=======================
33

4+
Dotenv
5+
------
6+
7+
* Deprecated passing `$usePutenv` argument to Dotenv's constructor, use `Dotenv::usePutenv()` instead.
8+
49
EventDispatcher
510
---------------
611

UPGRADE-6.0.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
UPGRADE FROM 5.x to 6.0
22
=======================
33

4+
Dotenv
5+
------
6+
7+
* Removed argument `$usePutenv` from Dotenv's constructor, use `Dotenv::usePutenv()` instead.
8+
49
EventDispatcher
510
---------------
611

src/Symfony/Component/Dotenv/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
CHANGELOG
22
=========
33

4+
5.1.0
5+
-----
6+
7+
* added `Dotenv::setProdEnvs()` and `Dotenv::usePutenv()`
8+
* made `Dotenv::loadEnv()` check for `env.local.php`
9+
* made Dotenv's constructor to accept `$envKey` and `$debugKey` arguments, to define
10+
the name of the env vars that configure the env name and debug settings
11+
* deprecated passing `$usePutenv` argument to Dotenv's constructor
12+
413
5.0.0
514
-----
615

src/Symfony/Component/Dotenv/Dotenv.php

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,47 @@ final class Dotenv
3535
private $data;
3636
private $end;
3737
private $values;
38-
private $usePutenv;
38+
private $envKey;
39+
private $debugKey;
40+
private $prodEnvs = ['prod'];
41+
private $usePutenv = false;
3942

4043
/**
41-
* @var bool If `putenv()` should be used to define environment variables or not.
42-
* Beware that `putenv()` is not thread safe, that's why this setting defaults to false
44+
* @param string|null $envKey
4345
*/
44-
public function __construct(bool $usePutenv = false)
46+
public function __construct($envKey = null, string $debugKey = null)
47+
{
48+
if (null !== $envKey && \in_array($envKey = (string) $envKey, ['1', ''], true)) {
49+
@trigger_error(sprintf('Passing a boolean to the constructor of "%s" is deprecated since Symfony 5.1, use "Dotenv::usePutenv()".', __CLASS__), E_USER_DEPRECATED);
50+
$this->usePutenv = (bool) $envKey;
51+
$envKey = null;
52+
}
53+
54+
$this->envKey = $envKey;
55+
$this->debugKey = $debugKey;
56+
}
57+
58+
/**
59+
* @return $this
60+
*/
61+
public function setProdEnvs(array $prodEnvs): self
62+
{
63+
$this->prodEnvs = $prodEnvs;
64+
65+
return $this;
66+
}
67+
68+
/**
69+
* @param bool $usePutenv If `putenv()` should be used to define environment variables or not.
70+
* Beware that `putenv()` is not thread safe, that's why this setting defaults to false
71+
*
72+
* 10000 @return $this
73+
*/
74+
public function usePutenv($usePutenv = true): self
4575
{
4676
$this->usePutenv = $usePutenv;
77+
78+
return $this;
4779
}
4880

4981
/**
@@ -67,32 +99,43 @@ public function load(string $path, string ...$extraPaths): void
6799
* .env.dist is loaded when it exists and .env is not found.
68100
*
69101
* @param string $path A file to load
70-
* @param string $varName The name of the env vars that defines the app env
102+
* @param string $envKey The name of the env vars that defines the app env
71103
* @param string $defaultEnv The app env to use when none is defined
72104
* @param array $testEnvs A list of app envs for which .env.local should be ignored
73105
*
74106
* @throws FormatException when a file has a syntax error
75107
* @throws PathException when a file does not exist or is not readable
76108
*/
77-
public function loadEnv(string $path, string $varName = 'APP_ENV', string $defaultEnv = 'dev', array $testEnvs = ['test']): void
109+
public function loadEnv(string $path, string $envKey = 'APP_ENV', string $defaultEnv = 'dev', array $testEnvs = ['test']): void
78110
{
111+
$envKey = null === $this->envKey || 1 < \func_num_args() ? $envKey : $this->envKey;
112+
113+
$p = $path.'.local.php';
114+
$env = (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($p)) || file_exists($p) ? include $p : null;
115+
116+
if (\is_array($env) && ($_SERVER[$envKey] ?? $_ENV[$envKey] ?? $env[$envKey] ?? null) === ($env[$envKey] ?? null)) {
117+
$this->populate($env);
118+
$env = $env[$envKey] ?? $defaultEnv;
119+
goto configure_debug;
120+
}
121+
79122
if (file_exists($path) || !file_exists($p = "$path.dist")) {
80123
$this->load($path);
81124
} else {
82125
$this->load($p);
83126
}
84127

85-
if (null === $env = $_SERVER[$varName] ?? $_ENV[$varName] ?? null) {
86-
$this->populate([$varName => $env = $defaultEnv]);
128+
if (null === $env = $_SERVER< 10000 /span>[$envKey] ?? $_ENV[$envKey] ?? null) {
129+
$this->populate([$envKey => $env = $defaultEnv]);
87130
}
88131

89132
if (!\in_array($env, $testEnvs, true) && file_exists($p = "$path.local")) {
90133
$this->load($p);
91-
$env = $_SERVER[$varName] ?? $_ENV[$varName] ?? $env;
134+
$env = $_SERVER[$envKey] ?? $_ENV[$envKey] ?? $env;
92135
}
93136

94137
if ('local' === $env) {
95-
return;
138+
goto configure_debug;
96139
}
97140

98141
if (file_exists($p = "$path.$env")) {
@@ -102,6 +145,14 @@ public function loadEnv(string $path, string $varName = 'APP_ENV', string $defau
102145
if (file_exists($p = "$path.$env.local")) {
103146
$this->load($p);
104147
}
148+
149+
configure_debug:
150+
if (null !== $debugKey = $this->debugKey) {
151+
$debug = $_SERVER[$debugKey] ?? $_ENV[$debugKey] ?? !\in_array($env, $this->prodEnvs);
152+
$_ENV[$debugKey] = (int) $debug || filter_var($debug, FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
153+
}
154+
155+
$_SERVER += $_ENV;
105156
}
106157

107158
/**

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

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class DotenvTest extends TestCase
2222
*/
2323
public function testParseWithFormatError($data, $error)
2424
{
25-
$dotenv = new Dotenv(true);
25+
$dotenv = new Dotenv();
2626

2727
try {
2828
$dotenv->parse($data);
@@ -66,7 +66,7 @@ public function getEnvDataWithFormatErrors()
6666
*/
6767
public function testParse($data, $expected)
6868
{
69-
$dotenv = new Dotenv(true);
69+
$dotenv = new Dotenv();
7070
$this->assertSame($expected, $dotenv->parse($data));
7171
}
7272

@@ -208,13 +208,11 @@ public function testLoad()
208208
file_put_contents($path1, 'FOO=BAR');
209209
file_put_contents($path2, 'BAR=BAZ');
210210

211-
(new Dotenv(true))->load($path1, $path2);
211+
(new Dotenv())->usePutenv()->load($path1, $path2);
212212

213213
$foo = getenv('FOO');
214214
$bar = getenv('BAR');
215215

216-
putenv('FOO');
217 93C6 -
putenv('BAR');
218216
unlink($path1);
219217
unlink($path2);
220218
rmdir($tmpdir);
@@ -239,41 +237,41 @@ public function testLoadEnv()
239237
// .env
240238

241239
file_put_contents($path, 'FOO=BAR');
242-
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
240+
(new Dotenv())->usePutenv()->loadEnv($path, 'TEST_APP_ENV');
243241
$this->assertSame('BAR', getenv('FOO'));
244242
$this->assertSame('dev', getenv('TEST_APP_ENV'));
245243

246244
// .env.local
247245

248246
$_SERVER['TEST_APP_ENV'] = 'local';
249247
file_put_contents("$path.local", 'FOO=localBAR');
250-
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
248+
(new Dotenv())->usePutenv()->loadEnv($path, 'TEST_APP_ENV');
251249
$this->assertSame('localBAR', getenv('FOO'));
252250

253251
// special case for test
254252

255253
$_SERVER['TEST_APP_ENV'] = 'test';
256-
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
254+
(new Dotenv())->usePutenv()->loadEnv($path, 'TEST_APP_ENV');
257255
$this->assertSame('BAR', getenv('FOO'));
258256

259257
// .env.dev
260258

261259
unset($_SERVER['TEST_APP_ENV']);
262260
file_put_contents("$path.dev", 'FOO=devBAR');
263-
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
261+
(new Dotenv())->usePutenv()->loadEnv($path, 'TEST_APP_ENV');
264262
$this->assertSame('devBAR', getenv('FOO'));
265263

266264
// .env.dev.local
267265

268266
file_put_contents("$path.dev.local", 'FOO=devlocalBAR');
269-
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
267+
(new Dotenv())->usePutenv()->loadEnv($path, 'TEST_APP_ENV');
270268
$this->assertSame('devlocalBAR', getenv('FOO'));
271269

272270
// .env.dist
273271

274272
unlink($path);
275273
file_put_contents("$path.dist", 'BAR=distBAR');
276-
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
274+
(new Dotenv())->usePutenv()->loadEnv($path, 'TEST_APP_ENV');
277275
$this->assertSame('distBAR', getenv('BAR'));
278276

279277
putenv('FOO');
@@ -305,7 +303,7 @@ public function testOverload()
305303
file_put_contents($path1, 'FOO=BAR');
306304
file_put_contents($path2, 'BAR=BAZ');
307305

308-
(new Dotenv(true))->overload($path1, $path2);
306+
(new Dotenv())->usePutenv()->overload($path1, $path2);
309307

310308
$foo = getenv('FOO');
311309
$bar = getenv('BAR');
@@ -323,15 +321,15 @@ public function testOverload()
323321
public function testLoadDirectory()
324322
{
325323
$this->expectException('Symfony\Component\Dotenv\Exception\PathException');
326-
$dotenv = new Dotenv(true);
324+
$dotenv = new Dotenv();
327325
$dotenv->load(__DIR__);
328326
}
329327

330328
public function testServerSuperglobalIsNotOverridden()
331329
{
332330
$originalValue = $_SERVER['argc'];
333331

334-
$dotenv = new Dotenv(true);
332+
$dotenv = new Dotenv();
335333
$dotenv->populate(['argc' => 'new_value']);
336334

337335
$this->assertSame($originalValue, $_SERVER['argc']);
@@ -342,7 +340,7 @@ public function testEnvVarIsNotOverridden()
342340
putenv('TEST_ENV_VAR=original_value');
343341
$_SERVER['TEST_ENV_VAR'] = 'original_value';
344342

345-
$dotenv = new Dotenv(true);
343+
$dotenv = (new Dotenv())->usePutenv();
346344
$dotenv->populate(['TEST_ENV_VAR' => 'new_value']);
347345

348346
$this->assertSame('original_value', getenv('TEST_ENV_VAR'));
@@ -352,7 +350,7 @@ public function testHttpVarIsPartiallyOverridden()
352350
{
353351
$_SERVER['HTTP_TEST_ENV_VAR'] = 'http_value';
354352

355-
$dotenv = new Dotenv(true);
353+
$dotenv = (new Dotenv())->usePutenv();
356354
$dotenv->populate(['HTTP_TEST_ENV_VAR' => 'env_value']);
357355

358356
$this->assertSame('env_value', getenv('HTTP_TEST_ENV_VAR'));
@@ -364,7 +362,7 @@ public function testEnvVarIsOverriden()
364362
{
365363
putenv('TEST_ENV_VAR_OVERRIDEN=original_value');
366364

367-
$dotenv = new Dotenv(true);
365+
$dotenv = (new Dotenv())->usePutenv();
368366
$dotenv->populate(['TEST_ENV_VAR_OVERRIDEN' => 'new_value'], true);
369367

370368
$this->assertSame('new_value', getenv('TEST_ENV_VAR_OVERRIDEN'));
@@ -386,7 +384,7 @@ public function testMemorizingLoadedVarsNamesInSpecialVar()
386384
unset($_SERVER['DATABASE_URL']);
387385
putenv('DATABASE_URL');
388386

389-
$dotenv = new Dotenv(true);
387+
$dotenv = (new Dotenv())->usePutenv();
390388
$dotenv->populate(['APP_DEBUG' => '1', 'DATABASE_URL' => 'mysql://root@localhost/db']);
391389

392390
$this->assertSame('APP_DEBUG,DATABASE_URL', getenv('SYMFONY_DOTENV_VARS'));
@@ -403,7 +401,7 @@ public function testMemorizingLoadedVarsNamesInSpecialVar()
403401
unset($_SERVER['DATABASE_URL']);
404402
putenv('DATABASE_URL');
405403

406-
$dotenv = new Dotenv(true);
404+
$dotenv = (new Dotenv())->usePutenv();
407405
$dotenv->populate(['APP_DEBUG' => '0', 'DATABASE_URL' => 'mysql://root@localhost/db']);
408406
$dotenv->populate(['DATABASE_URL' => 'sqlite:///somedb.sqlite']);
409407

@@ -419,7 +417,7 @@ public function testOverridingEnvVarsWithNamesMemorizedInSpecialVar()
419417
putenv('BAZ=baz');
420418
putenv('DOCUMENT_ROOT=/var/www');
421419

422-
$dotenv = new Dotenv(true);
420+
$dotenv = (new Dotenv())->usePutenv();
423421
$dotenv->populate(['FOO' => 'foo1', 'BAR' => 'bar1', 'BAZ' => 'baz1', 'DOCUMENT_ROOT' => '/boot']);
424422

425423
$this->assertSame('foo1', getenv('FOO'));
@@ -431,7 +429,7 @@ public function testOverridingEnvVarsWithNamesMemorizedInSpecialVar()
431429
public function testGetVariablesValueFromEnvFirst()
432430
{
433431
$_ENV['APP_ENV'] = 'prod';
434-
$dotenv = new Dotenv(true);
432+
$dotenv = new Dotenv();
435433

436434
$test = "APP_ENV=dev\nTEST1=foo1_\${APP_ENV}";
437435
$values = $dotenv->parse($test);
@@ -448,7 +446,7 @@ public function testGetVariablesValueFromGetenv()
448446
{
449447
putenv('Foo=Bar');
450448

451-
$dotenv = new Dotenv(true);
449+
$dotenv = new Dotenv();
452450

453451
try {
454452
$values = $dotenv->parse('Foo=${Foo}');
@@ -460,15 +458,13 @@ public function testGetVariablesValueFromGetenv()
460458

461459
public function testNoDeprecationWarning()
462460
{
463-
$dotenv = new Dotenv(true);
464-
$this->assertInstanceOf(Dotenv::class, $dotenv);
465-
$dotenv = new Dotenv(false);
461+
$dotenv = new Dotenv();
466462
$this->assertInstanceOf(Dotenv::class, $dotenv);
467463
}
468464

469465
public function testDoNotUsePutenv()
470466
{
471-
$dotenv = new Dotenv(false);
467+
$dotenv = new Dotenv();
472468
$dotenv->populate(['TEST_USE_PUTENV' => 'no']);
473469

474470
$this->assertSame('no', $_SERVER['TEST_USE_PUTENV']);

0 commit comments

Comments
 (0)
0