Skip to content

Commit cb0b07e

Browse files
feature #40682 [DependencyInjection] Add env() and EnvConfigurator in the PHP-DSL (fancyweb)
This PR was merged into the 5.3-dev branch. Discussion ---------- [DependencyInjection] Add env() and EnvConfigurator in the PHP-DSL | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Recently, I have been using env var processors a lot. This is a proposition to improve the DX a bit when you use the PHP-DSL to configure services. Firstly, I am "annoyed" by the fact that I can do `param('my_param')` but not `env('MY_ENV')`. Secondly, long chains of env var processors (eg: `%env(default:my_param:key:path:url:MY_ENV_VAR)` have two issues: - you must construct and read them in "reverse" - some env var processor are actually composed of 2 parts (key:path), you don't distinguish them easily from the rest Before: ```php ->arg('$myArg', '%env(default:my_param:key:path:url:MY_ENV_VAR)%') ``` After: ```php ->arg( '$myArg', env('MY_ENV_VAR') ->url() ->key('path') ->default('my_param') ) ``` Custom env var processor would be callable with `->custom('my_custom_env_var_processor')` or you could extend the configurator and add your own methods. WDYT? Commits ------- 5f0fe32 [DependencyInjection] Add env() and EnvConfigurator in the PHP-DSL
2 parents b40eac2 + 5f0fe32 commit cb0b07e

File tree

7 files changed

+284
-0
lines changed

7 files changed

+284
-0
lines changed

src/Symfony/Component/DependencyInjection/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CHANGELOG
1212
* Add support for per-env configuration in loaders
1313
* Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
1414
* Add support an integer return value for default_index_method
15+
* Add `env()` and `EnvConfigurator` in the PHP-DSL
1516

1617
5.2.0
1718
-----

src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php

+4
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ public static function processValue($value, $allowServices = false)
8383
return $def;
8484
}
8585

86+
if ($value instanceof EnvConfigurator) {
87+
return (string) $value;
88+
}
89+
8690
if ($value instanceof self) {
8791
throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY));
8892
}

src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php

+8
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,11 @@ function abstract_arg(string $description): AbstractArgument
201201
{
202202
return new AbstractArgument($description);
203203
}
204+
205+
/**
206+
* Creates an environment variable reference.
207+
*/
208+
function env(string $name): EnvConfigurator
209+
{
210+
return new EnvConfigurator($name);
211+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
class EnvConfigurator
15+
{
16+
/**
17+
* @var string[]
18+
*/
19+
private $stack;
20+
21+
public function __construct(string $name)
22+
{
23+
$this->stack = explode(':', $name);
24+
}
25+
26+
/**
27+
* @return string
28+
*/
29+
public function __toString()
30+
{
31+
return '%env('.implode(':', $this->stack).')%';
32+
}
33+
34+
/**
35+
* @return $this
36+
*/
37+
public function custom(string $processor, ...$args): self
38+
{
39+
array_unshift($this->stack, $processor, ...$args);
40+
41+
return $this;
42+
}
43+
44+
/**
45+
* @return $this
46+
*/
47+
public function base64(): self
48+
{
49+
array_unshift($this->stack, 'base64');
50+
51+
return $this;
52+
}
53+
54+
/**
55+
* @return $this
56+
*/
57+
public function bool(): self
58+
{
59+
array_unshift($this->stack, 'bool');
60+
61+
return $this;
62+
}
63+
64+
/**
65+
* @return $this
66+
*/
67+
public function not(): self
68+
{
69+
array_unshift($this->stack, 'not');
70+
71+
return $this;
72+
}
73+
74+
/**
75+
* @return $this
76+
*/
77+
public function const(): self
78+
{
79+
array_unshift($this->stack, 'const');
80+
81+
return $this;
82+
}
83+
84+
/**
85+
* @return $this
86+
*/
87+
public function csv(): self
88+
{
89+
array_unshift($this->stack, 'csv');
90+
91+
return $this;
92+
}
93+
94+
/**
95+
* @return $this
96+
*/
97+
public function file(): self
98+
{
99+
array_unshift($this->stack, 'file');
100+
101+
return $this;
102+
}
103+
104+
/**
105+
* @return $this
106+
*/
107+
public function float(): self
108+
{
109+
array_unshift($this->stack, 'float');
110+
111+
return $this;
112+
}
113+
114+
/**
115+
* @return $this
116+
*/
117+
public function int(): self
118+
{
119+
array_unshift($this->stack, 'int');
120+
121+
return $this;
122+
}
123+
124+
/**
125+
* @return $this
126+
*/
127+
public function json(): self
128+
{
129+
array_unshift($this->stack, 'json');
130+
131+
return $this;
132+
}
133+
134+
/**
135+
* @return $this
136+
*/
137+
public function key(string $key): self
138+
{
139+
array_unshift($this->stack, 'key', $key);
140+
141+
return $this;
142+
}
143+
144+
/**
145+
* @return $this
146+
*/
147+
public function url(): self
148+
{
149+
array_unshift($this->stack, 'url');
150+
151+
return $this;
152+
}
153+
154+
/**
155+
* @return $this
156+
*/
157+
public function queryString(): self
158+
{
159+
array_unshift($this->stack, 'query_string');
160+
161+
return $this;
162+
}
163+
164+
/**
165+
* @return $this
166+
*/
167+
public function resolve(): self
168+
{
169+
array_unshift($this->stack, 'resolve');
170+
171+
return $this;
172+
}
173+
174+
/**
175+
* @return $this
176+
*/
177+
public function default(string $fallbackParam): self
178+
{
179+
array_unshift($this->stack, 'default', $fallbackParam);
180+
181+
return $this;
182+
}
183+
184+
/**
185+
* @return $this
186+
*/
187+
public function string(): self
188+
{
189+
array_unshift($this->stack, 'string');
190+
191+
return $this;
192+
}
193+
194+
/**
195+
* @return $this
196+
*/
197+
public function trim(): self
198+
{
199+
array_unshift($this->stack, 'trim');
200+
201+
return $this;
202+
}
203+
204+
/**
205+
* @return $this
206+
*/
207+
public function require(): self
208+
{
209+
array_unshift($this->stack, 'require');
210+
211+
return $this;
212+
}
213+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
4+
5+
return static function (ContainerConfigurator $configurator): void {
6+
$services = $configurator->services();
7+
8+
$services
9+
->set('foo', \stdClass::class)
10+
->public()
11+
->args([
12+
env('CCC')->int()
13+
]);
14+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Loader\Configurator;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Loader\Configurator\EnvConfigurator;
16+
17+
final class EnvConfiguratorTest extends TestCase
18+
{
19+
/**
20+
* @dataProvider provide
21+
*/
22+
public function test(string $expected, EnvConfigurator $envConfigurator)
23+
{
24+
$this->assertSame($expected, (string) $envConfigurator);
25+
}
26+
27+
public function provide()
28+
{
29+
yield ['%env(FOO)%', new EnvConfigurator('FOO')];
30+
yield ['%env(string:FOO)%', new EnvConfigurator('string:FOO')];
31+
yield ['%env(string:FOO)%', (new EnvConfigurator('FOO'))->string()];
32+
yield ['%env(key:path:url:FOO)%', (new EnvConfigurator('FOO'))->url()->key('path')];
33+
yield ['%env(default:fallback:bar:arg1:FOO)%', (new EnvConfigurator('FOO'))->custom('bar', 'arg1')->default('fallback')];
34+
}
35+
}

src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ public function testWhenEnv()
147147
$this->assertSame(['foo' => 234, 'bar' => 345], $container->getParameterBag()->all());
148148
}
149149

150+
public function testEnvConfigurator()
151+
{
152+
$container = new ContainerBuilder();
153+
$loader = new PhpFileLoader($container, new FileLocator(realpath(__DIR__.'/../Fixtures').'/config'), 'some-env');
154+
$loader->load('env_configurator.php');
155+
156+
$this->assertSame('%env(int:CCC)%', $container->getDefinition('foo')->getArgument(0));
157+
}
158+
150159
/**
151160
* @group legacy
152161
*/

0 commit comments

Comments
 (0)