Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit09ba274

Browse files
feature#59704 [DependencyInjection] AddDefinition::addExcludedTag() andContainerBuilder::findExcludedServiceIds() for auto-discovering value-objects (GromNaN)
This PR was squashed before being merged into the 7.3 branch.Discussion----------[DependencyInjection] Add `Definition::addExcludedTag()` and `ContainerBuilder::findExcludedServiceIds()` for auto-discovering value-objects| Q | A| ------------- | ---| Branch? | 7.3| Bug fix? | no| New feature? | yes| Deprecations? | no| Issues | -| License | MITWe could **not** use the method `findTaggedServiceIds` in#59401 (comment), same forapi-platform/core#6943.As "using the container loading tools to do resource discovery quite seamlessly" [seems to be a good idea](#59401 (review)), this changes make it easier.I'm not closed to alternative ideas if we want to go further with this use-case.### UsageLet's create a `AppModel` attribute class and use it on any class of the project.In the extension class:```php$this->registerAttributeForAutoconfiguration(AppModel::class, static function (ChildDefinition $definition) { $definition->addExcludedTag('app.model');});```In a compiler pass:```php$classes = [];foreach($containerBuilder->findExcludedServiceIds('app.model') as $id => $tags) { $classes[] = $containerBuilder->getDefinition($id)->getClass();}$containerBuilder->setParameter('.app.model_classes', $classes);```And this parameter can be injected into a service, or directly update a service definition to inject this list of classes. The attribute parameters can be injected into the tag, and retrieved in the compiler pass, for more advanced configuration.Commits-------7a0443b [DependencyInjection] Add `Definition::addExcludedTag()` and `ContainerBuilder::findExcludedServiceIds()` for auto-discovering value-objects
2 parents4b6f05d +7a0443b commit09ba274

File tree

5 files changed

+104
-9
lines changed

5 files changed

+104
-9
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ CHANGELOG
77
* Make`#[AsTaggedItem]` repeatable
88
* Support`@>` as a shorthand for`!service_closure` in yaml files
99
* Don't skip classes with private constructor when autodiscovering
10+
* Add`Definition::addExcludeTag()` and`ContainerBuilder::findExcludedServiceIds()`
11+
for auto-configuration of classes excluded from the service container
1012

1113
7.2
1214
---

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,38 @@ public function findTaggedServiceIds(string $name, bool $throwOnAbstract = false
13511351
return$tags;
13521352
}
13531353

1354+
/**
1355+
* Returns service ids for a given tag, asserting they have the "container.excluded" tag.
1356+
*
1357+
* Example:
1358+
*
1359+
* $container->register('foo')->addExcludeTag('my.tag', ['hello' => 'world'])
1360+
*
1361+
* $serviceIds = $container->findExcludedServiceIds('my.tag');
1362+
* foreach ($serviceIds as $serviceId => $tags) {
1363+
* foreach ($tags as $tag) {
1364+
* echo $tag['hello'];
1365+
* }
1366+
* }
1367+
*
1368+
* @return array<string, array> An array of tags with the tagged service as key, holding a list of attribute arrays
1369+
*/
1370+
publicfunctionfindExcludedServiceIds(string$tagName):array
1371+
{
1372+
$this->usedTags[] =$tagName;
1373+
$tags = [];
1374+
foreach ($this->getDefinitions()as$id =>$definition) {
1375+
if ($definition->hasTag($tagName)) {
1376+
if (!$definition->hasTag('container.excluded')) {
1377+
thrownewInvalidArgumentException(\sprintf('The service "%s" tagged "%s" is missing the "container.excluded" tag.',$id,$tagName));
1378+
}
1379+
$tags[$id] =$definition->getTag($tagName);
1380+
}
1381+
}
1382+
1383+
return$tags;
1384+
}
1385+
13541386
/**
13551387
* Returns all tags the defined services use.
13561388
*

‎src/Symfony/Component/DependencyInjection/Definition.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,20 @@ public function addTag(string $name, array $attributes = []): static
455455
return$this;
456456
}
457457

458+
/**
459+
* Adds a tag to the definition and marks it as excluded.
460+
*
461+
* These definitions should be processed using {@see ContainerBuilder::findExcludedServiceIds()}
462+
*
463+
* @return $this
464+
*/
465+
publicfunctionaddExcludeTag(string$name,array$attributes = []):static
466+
{
467+
return$this->addTag($name,$attributes)
468+
->addTag('container.excluded', ['source' =>\sprintf('by tag "%s"',$name)])
469+
->setAbstract(true);
470+
}
471+
458472
/**
459473
* Whether this definition has a tag with the given name.
460474
*/

‎src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,20 +1062,18 @@ public function testMergeLogicException()
10621062
$container->merge(newContainerBuilder());
10631063
}
10641064

1065-
publicfunctiontestfindTaggedServiceIds()
1065+
publicfunctiontestFindTaggedServiceIds()
10661066
{
10671067
$builder =newContainerBuilder();
1068-
$builder
1069-
->register('foo','Bar\FooClass')
1068+
$builder->register('foo','Bar\FooClass')
1069+
->setAbstract(true)
10701070
->addTag('foo', ['foo' =>'foo'])
10711071
->addTag('bar', ['bar' =>'bar'])
1072-
->addTag('foo', ['foofoo' =>'foofoo'])
1073-
;
1074-
$builder
1075-
->register('bar','Bar\FooClass')
1072+
->addTag('foo', ['foofoo' =>'foofoo']);
1073+
$builder->register('bar','Bar\FooClass')
10761074
->addTag('foo')
1077-
->addTag('container.excluded')
1078-
;
1075+
->addTag('container.excluded');
1076+
10791077
$this->assertEquals([
10801078
'foo' => [
10811079
['foo' =>'foo'],
@@ -1085,6 +1083,45 @@ public function testfindTaggedServiceIds()
10851083
$this->assertEquals([],$builder->findTaggedServiceIds('foobar'),'->findTaggedServiceIds() returns an empty array if there is annotated services');
10861084
}
10871085

1086+
publicfunctiontestFindTaggedServiceIdsThrowsWhenAbstract()
1087+
{
1088+
$builder =newContainerBuilder();
1089+
$builder->register('foo','Bar\FooClass')
1090+
->setAbstract(true)
1091+
->addTag('foo', ['foo' =>'foo']);
1092+
1093+
$this->expectException(InvalidArgumentException::class);
1094+
$this->expectExceptionMessage('The service "foo" tagged "foo" must not be abstract.');
1095+
$builder->findTaggedServiceIds('foo',true);
1096+
}
1097+
1098+
publicfunctiontestFindExcludedServiceIds()
1099+
{
1100+
$builder =newContainerBuilder();
1101+
$builder->register('myservice','Bar\FooClass')
1102+
->addTag('foo', ['foo' =>'foo'])
1103+
->addTag('bar', ['bar' =>'bar'])
1104+
->addTag('foo', ['foofoo' =>'foofoo'])
1105+
->addExcludeTag('container.excluded');
1106+
1107+
$expected = ['myservice' => [['foo' =>'foo'], ['foofoo' =>'foofoo']]];
1108+
$this->assertSame($expected,$builder->findExcludedServiceIds('foo'));
1109+
$this->assertSame([],$builder->findExcludedServiceIds('foofoo'));
1110+
}
1111+
1112+
publicfunctiontestFindExcludedServiceIdsThrowsWhenNotExcluded()
1113+
{
1114+
$builder =newContainerBuilder();
1115+
$builder->register('myservice','Bar\FooClass')
1116+
->addTag('foo', ['foo' =>'foo'])
1117+
->addTag('bar', ['bar' =>'bar'])
1118+
->addTag('foo', ['foofoo' =>'foofoo']);
1119+
1120+
$this->expectException(InvalidArgumentException::class);
1121+
$this->expectExceptionMessage('The service "myservice" tagged "foo" is missing the "container.excluded" tag.');
1122+
$builder->findExcludedServiceIds('foo',true);
1123+
}
1124+
10881125
publicfunctiontestFindUnusedTags()
10891126
{
10901127
$builder =newContainerBuilder();

‎src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,16 @@ public function testTags()
258258
],$def->getTags(),'->getTags() returns all tags');
259259
}
260260

261+
publicfunctiontestAddExcludeTag()
262+
{
263+
$def =newDefinition('stdClass');
264+
$def->addExcludeTag('foo', ['bar' =>true]);
265+
266+
$this->assertSame([['bar' =>true]],$def->getTag('foo'));
267+
$this->assertTrue($def->isAbstract());
268+
$this->assertSame([['source' =>'by tag "foo"']],$def->getTag('container.excluded'));
269+
}
270+
261271
publicfunctiontestSetArgument()
262272
{
263273
$def =newDefinition('stdClass');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp