8000 feature #31062 [Dotenv] Deprecate useage of "putenv" (Nyholm) · symfony/symfony@b6c6338 · GitHub
[go: up one dir, main page]

Skip to content

Commit b6c6338

Browse files
committed
feature #31062 [Dotenv] Deprecate useage of "putenv" (Nyholm)
This PR was squashed before being merged into the 4.3-dev branch (closes #31062). Discussion ---------- [Dotenv] Deprecate useage of "putenv" | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | n/a From discussions on symfony/recipes#571, I think it is a good idea to make people opt-in to using `putenv`. In Symfony 5.0 we will just change the value of the constructor. As an alternative, we could decide we want to remove `putenv` in Symfony 5.0. If so, I would also deprecate `$usePutenv=true`. Commits ------- 8e45fc0 [Dotenv] Deprecate useage of \"putenv\"
2 parents a7ce547 + 8e45fc0 commit b6c6338

File tree

5 files changed

+71
-21
lines changed

5 files changed

+71
-21
lines changed

UPGRADE-4.3.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ Doctrine Bridge
4545
* Passing an `IdReader` to the `DoctrineChoiceLoader` when the query cannot be optimized with single id field has been deprecated, pass `null` instead
4646
* Not passing an `IdReader` to the `DoctrineChoiceLoader` when the query can be optimized with single id field has been deprecated
4747

48+
Dotenv
49+
------
50+
51+
* First parameter of `Dontenv::__construct()` will change from `true` to `false` in Symfony 5.0. A deprecation warning
52+
will be triggered if no parameter is used. Use `$usePutenv=true` to upgrade without breaking changes.
53+
4854
EventDispatcher
4955
---------------
5056

src/Symfony/Component/Dotenv/CHANGELOG.md

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

4+
4.3.0
5+
-----
6+
7+
* deprecated use of `putenv()` but default. This feature will be opted-in with a constructor argument to `Dotenv`.
8+
49
4.2.0
510
-----
611

src/Symfony/Component/Dotenv/Dotenv.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ final class Dotenv
3535
private $data;
3636
private $end;
3737
private $values;
38+
private $usePutenv = true;
39+
40+
/**
41+
* @var bool If we should use `putenv()` to define environment variables
42+
* or not. Since Symfony 5.0 the default value is false
43+
* because `putenv()` is not thread safe.
44+
*/
45+
public function __construct(bool $usePutenv = true)
46+
{
47+
if (0 === \func_num_args()) {
48+
@trigger_error(sprintf('The default value of "$usePutenv" argument of "%s\'s constructor will change from "true" to "false" in Symfony 5.0, you should define its value explicitly.', __METHOD__), E_USER_DEPRECATED);
49+
}
50+
51+
$this->usePutenv = $usePutenv;
52+
}
3853

3954
/**
4055
* Loads one or several .env files.
@@ -126,7 +141,10 @@ public function populate(array $values, bool $overrideExistingVars = false): voi
126141
continue;
127142
}
128143

129-
putenv("$name=$value");
144+
if ($this->usePutenv) {
145+
putenv("$name=$value");
146+
}
147+
130148
$_ENV[$name] = $value;
131149
if ($notHttpName) {
132150
$_SERVER[$name] = $value;
@@ -140,7 +158,11 @@ public function populate(array $values, bool $overrideExistingVars = false): voi
140158
if ($updateLoadedVars) {
141159
unset($loadedVars['']);
142160
$loadedVars = implode(',', array_keys($loadedVars));
143-
putenv('SYMFONY_DOTENV_VARS='.$_ENV['SYMFONY_DOTENV_VARS'] = $_SERVER['SYMFONY_DOTENV_VARS'] = $loadedVars);
161+
$_ENV['SYMFONY_DOTENV_VARS'] = $_SERVER['SYMFONY_DOTENV_VARS'] = $loadedVars;
162+
163+
if ($this->usePutenv) {
164+
putenv('SYMFONY_DOTENV_VARS='.$loadedVars);
165+
}
144166
}
145167
}
146168

src/Symfony/Component/Dotenv/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Dotenv Component
22
================
33

44
Symfony Dotenv parses `.env` files to make environment variables stored in them
5-
accessible via `getenv()`, `$_ENV`, or `$_SERVER`.
5+
accessible via `$_ENV`, `$_SERVER` and optionally `getenv()`.
66

77
Resources
88
---------

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

Lines changed: 35 additions & 18 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();
25+
$dotenv = new Dotenv(true);
2626

2727
try {
2828
$dotenv->parse($data);
@@ -62,7 +62,7 @@ public function getEnvDataWithFormatErrors()
6262
*/
6363
public function testParse($data, $expected)
6464
{
65-
$dotenv = new Dotenv();
65+
$dotenv = new Dotenv(true);
6666
$this->assertSame($expected, $dotenv->parse($data));
6767
}
6868

@@ -193,7 +193,7 @@ public function testLoad()
193193
file_put_contents($path1, 'FOO=BAR');
194194
file_put_contents($path2, 'BAR=BAZ');
195195

196-
(new Dotenv())->load($path1, $path2);
196+
(new Dotenv(true))->load($path1, $path2);
197197

198198
$foo = getenv('FOO');
199199
$bar = getenv('BAR');
@@ -224,41 +224,41 @@ public function testLoadEnv()
224224
// .env
225225

226226
file_put_contents($path, 'FOO=BAR');
227-
(new DotEnv())->loadEnv($path, 'TEST_APP_ENV');
227+
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
228228
$this->assertSame('BAR', getenv('FOO'));
229229
$this->assertSame('dev', getenv('TEST_APP_ENV'));
230230

231231
// .env.local
232232

233233
$_SERVER['TEST_APP_ENV'] = 'local';
234234
file_put_contents("$path.local", 'FOO=localBAR');
235-
(new DotEnv())->loadEnv($path, 'TEST_APP_ENV');
235+
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
236236
$this->assertSame('localBAR', getenv('FOO'));
237237

238238
// special case for test
239239

240240
$_SERVER['TEST_APP_ENV'] = 'test';
241-
(new DotEnv())->loadEnv($path, 'TEST_APP_ENV');
241+
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
242242
$this->assertSame('BAR', getenv('FOO'));
243243

244244
// .env.dev
245245

246246
unset($_SERVER['TEST_APP_ENV']);
247247
file_put_contents("$path.dev", 'FOO=devBAR');
248-
(new DotEnv())->loadEnv($path, 'TEST_APP_ENV');
248+
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
249249
$this->assertSame('devBAR', getenv('FOO'));
250250

251251
// .env.dev.local
252252

253253
file_put_contents("$path.dev.local", 'FOO=devlocalBAR');
254-
(new DotEnv())->loadEnv($path, 'TEST_APP_ENV');
254+
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
255255
$this->assertSame('devlocalBAR', getenv('FOO'));
256256

257257
// .env.dist
258258

259259
unlink($path);
260260
file_put_contents("$path.dist", 'BAR=distBAR');
261-
(new DotEnv())->loadEnv($path, 'TEST_APP_ENV');
261+
(new Dotenv(true))->loadEnv($path, 'TEST_APP_ENV');
262262
$this->assertSame('distBAR', getenv('BAR'));
263263

264264
putenv('FOO');
@@ -290,7 +290,7 @@ public function testOverload()
290290
file_put_contents($path1, 'FOO=BAR');
291291
file_put_contents($path2, 'BAR=BAZ');
292292

293-
(new Dotenv())->overload($path1, $path2);
293+
(new Dotenv(true))->overload($path1, $path2);
294294

295295
$foo = getenv('FOO');
296296
$bar = getenv('BAR');
@@ -310,15 +310,15 @@ public function testOverload()
310310
*/
311311
public function testLoadDirectory()
312312
{
313-
$dotenv = new Dotenv();
313+
$dotenv = new Dotenv(true);
314314
$dotenv->load(__DIR__);
315315
}
316316

317317
public function testServerSuperglobalIsNotOverriden()
318318
{
319319
$originalValue = $_SERVER['argc'];
320320

321-
$dotenv = new Dotenv();
321+
$dotenv = new Dotenv(true);
322322
$dotenv->populate(['argc' => 'new_value']);
323323

324324
$this->assertSame($originalValue, $_SERVER['argc']);
@@ -329,7 +329,7 @@ public function testEnvVarIsNotOverriden()
329329
putenv('TEST_ENV_VAR=original_value');
330330
$_SERVER['TEST_ENV_VAR'] = 'original_value';
331331

332-
$dotenv = new Dotenv();
332+
$dotenv = new Dotenv(true);
333333
$dotenv->populate(['TEST_ENV_VAR' => 'new_value']);
334334

335335
$this->assertSame('original_value', getenv('TEST_ENV_VAR'));
@@ -339,7 +339,7 @@ public function testHttpVarIsPartiallyOverriden()
339339
{
340340
$_SERVER['HTTP_TEST_ENV_VAR'] = 'http_value';
341341

342-
$dotenv = new Dotenv();
342+
$dotenv = new Dotenv(true);
343343
$dotenv->populate(['HTTP_TEST_ENV_VAR' => 'env_value']);
344344

345345
$this->assertSame('env_value', getenv('HTTP_TEST_ENV_VAR'));
@@ -351,7 +351,7 @@ public function testEnvVarIsOverriden()
351351
{
352352
putenv('TEST_ENV_VAR_OVERRIDEN=original_value');
353353

354-
$dotenv = new Dotenv();
354+
$dotenv = new Dotenv(true);
355355
$dotenv->populate(['TEST_ENV_VAR_OVERRIDEN' => 'new_value'], true);
356356

357357
$this->assertSame('new_value', getenv('TEST_ENV_VAR_OVERRIDEN'));
@@ -373,7 +373,7 @@ public function testMemorizingLoadedVarsNamesInSpecialVar()
373373
unset($_SERVER['DATABASE_URL']);
374374
putenv('DATABASE_URL');
375375

376-
$dotenv = new Dotenv();
376+
$dotenv = new Dotenv(true);
377377
$dotenv->populate(['APP_DEBUG' => '1', 'DATABASE_URL' => 'mysql://root@localhost/db']);
378378

379379
$this->assertSame('APP_DEBUG,DATABASE_URL', getenv('SYMFONY_DOTENV_VARS'));
@@ -390,7 +390,7 @@ public function testMemorizingLoadedVarsNamesInSpecialVar()
390390
unset($_SERVER['DATABASE_URL']);
391391
putenv('DATABASE_URL');
392392

393-
$dotenv = new Dotenv();
393+
$dotenv = new Dotenv(true);
394394
$dotenv->populate(['APP_DEBUG' => '0', 'DATABASE_URL' => 'mysql://root@localhost/db']);
395395
$dotenv->populate(['DATABASE_URL' => 'sqlite:///somedb.sqlite']);
396396

@@ -406,12 +406,29 @@ public function testOverridingEnvVarsWithNamesMemorizedInSpecialVar()
406406
putenv('BAZ=baz');
407407
putenv('DOCUMENT_ROOT=/var/www');
408408

409-
$dotenv = new Dotenv();
409+
$dotenv = new Dotenv(true);
410410
$dotenv->populate(['FOO' => 'foo1', 'BAR' => 'bar1', 'BAZ' => 'baz1', 'DOCUMENT_ROOT' => '/boot']);
411411

412412
$this->assertSame('foo1', getenv('FOO'));
413413
$this->assertSame('bar1', getenv('BAR'));
414414
$this->assertSame('baz1', getenv('BAZ'));
415415
$this->assertSame('/var/www', getenv('DOCUMENT_ROOT'));
416416
}
417+
418+
/**
419+
* @group legacy
420+
* @expectedDeprecation The default value of "$usePutenv" argument of "%s's constructor will change from "true" to "false" in Symfony 5.0, you should define its value explicitly.
421+
*/
422+
public function testDeprecationWarning()
423+
{
424+
new Dotenv();
425+
}
426+
427+
public function testNoDeprecationWarning()
428+
{
429+
$dotenv = new Dotenv(true);
430+
$this->assertInstanceOf(Dotenv::class, $dotenv);
431+
$dotenv = new Dotenv(false);
432+
$this->assertInstanceOf(Dotenv::class, $dotenv);
433+
}
417434
}

0 commit comments

Comments
 (0)
0