Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4cac9cf

Browse filesBrowse files
feature #40782 [DependencyInjection] Add #[When(env: 'foo')] to skip autoregistering a class when the env doesn't match (nicolas-grekas)
This PR was merged into the 5.3-dev branch. Discussion ---------- [DependencyInjection] Add `#[When(env: 'foo')]` to skip autoregistering a class when the env doesn't match | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - This is a follow up of #40214, in order to conditionally auto-register classes. By adding a `#[When(env: prod)]` annotation on a class, one can tell that a class should be skipped when the current env doesn't match the one declared in the attribute. This saves from writing similar conditional configuration by using the per-env `services_prod.yaml` convention (+corresponding exclusion from `services.yaml`), or some logic in the Kernel. Commits ------- 59c75ba [DI] add `#[When(env: 'foo')]` to skip autoregistering a class when the env doesn't match
2 parents 2edebff + 59c75ba commit 4cac9cf
Copy full SHA for 4cac9cf

File tree

7 files changed

+83
-3
lines changed
Filter options

7 files changed

+83
-3
lines changed
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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\Attribute;
13+
14+
/**
15+
* An attribute to tell under which environement this class should be registered as a service.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
20+
class When
21+
{
22+
public function __construct(
23+
public string $env,
24+
) {
25+
}
26+
}

‎src/Symfony/Component/DependencyInjection/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CHANGELOG
1313
* Add support for per-env configuration in XML and Yaml loaders
1414
* Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
1515
* Add support an integer return value for default_index_method
16+
* Add `#[When(env: 'foo')]` to skip autoregistering a class when the env doesn't match
1617
* Add `env()` and `EnvConfigurator` in the PHP-DSL
1718
* Add support for `ConfigBuilder` in the `PhpFileLoader`
1819
* Add `ContainerConfigurator::env()` to get the current environment

‎src/Symfony/Component/DependencyInjection/Loader/FileLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
+17-1Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
1818
use Symfony\Component\Config\Loader\Loader;
1919
use Symfony\Component\Config\Resource\GlobResource;
20+
use Symfony\Component\DependencyInjection\Attribute\When;
2021
use Symfony\Component\DependencyInjection\ChildDefinition;
2122
use Symfony\Component\DependencyInjection\Compiler\RegisterAutoconfigureAttributesPass;
2223
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -98,11 +99,26 @@ public function registerClasses(Definition $prototype, string $namespace, string
9899
}
99100

100101
$autoconfigureAttributes = new RegisterAutoconfigureAttributesPass();
101-
$classes = $this->findClasses($namespace, $resource, (array) $exclude, $autoconfigureAttributes->accept($prototype) ? $autoconfigureAttributes : null);
102+
$autoconfigureAttributes = $autoconfigureAttributes->accept($prototype) ? $autoconfigureAttributes : null;
103+
$classes = $this->findClasses($namespace, $resource, (array) $exclude, $autoconfigureAttributes);
102104
// prepare for deep cloning
103105
$serializedPrototype = serialize($prototype);
104106

105107
foreach ($classes as $class => $errorMessage) {
108+
if ($autoconfigureAttributes && $this->env) {
109+
$r = $this->container->getReflectionClass($class);
110+
$attribute = null;
111+
foreach ($r->getAttributes(When::class) as $attribute) {
112+
if ($this->env === $attribute->newInstance()->env) {
113+
$attribute = null;
114+
break;
115+
}
116+
}
117+
if (null !== $attribute) {
118+
continue;
119+
}
120+
}
121+
106122
if (interface_exists($class, false)) {
107123
$this->interfaces[] = $class;
108124
} else {

‎src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ public function load($resource, string $type = null)
5050

5151
$this->container->fileExists($path);
5252

53-
$this->loadXml($xml, $path);
53+
$env = $this->env;
54+
$this->env = null;
55+
try {
56+
$this->loadXml($xml, $path);
57+
} finally {
58+
$this->env = $env;
59+
}
5460

5561
if ($this->env) {
5662
$xpath = new \DOMXPath($xml);

‎src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,13 @@ public function load($resource, string $type = null)
129129
return;
130130
}
131131

132-
$this->loadContent($content, $path);
132+
$env = $this->env;
133+
$this->env = null;
134+
try {
135+
$this->loadContent($content, $path);
136+
} finally {
137+
$this->env = $env;
138+
}
133139

134140
// per-env configuration
135141
if ($this->env && isset($content['when@'.$this->env])) {

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
44

5+
use Symfony\Component\DependencyInjection\Attribute\When;
6+
7+
#[When(env: 'prod')]
8+
#[When(env: 'dev')]
59
class Foo implements FooInterface, Sub\BarInterface
610
{
711
public function __construct($bar = null)

‎src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,27 @@ public function testRegisterClassesWithIncompatibleExclude()
243243
'yaml/*'
244244
);
245245
}
246+
247+
/**
248+
* @requires PHP 8
249+
*
250+
* @testWith ["prod", true]
251+
* ["dev", true]
252+
* ["bar", false]
253+
* [null, true]
254+
*/
255+
public function testRegisterClassesWithWhenEnv(?string $env, bool $expected)
256+
{
257+
$container = new ContainerBuilder();
258+
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'), $env);
259+
$loader->registerClasses(
260+
(new Definition())->setAutoconfigured(true),
261+
'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\',
262+
'Prototype/{Foo.php}'
263+
);
264+
265+
$this->assertSame($expected, $container->has(Foo::class));
266+
}
246267
}
247268

248269
class TestFileLoader extends FileLoader

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.