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

Commit78018de

Browse files
[DependencyInjection] Add#[AutowireIterator] attribute and improve#[AutowireLocator]
1 parent7be1c03 commit78018de

File tree

9 files changed

+129
-48
lines changed

9 files changed

+129
-48
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
namespaceSymfony\Component\DependencyInjection\Attribute;
13+
14+
useSymfony\Component\DependencyInjection\Argument\IteratorArgument;
15+
useSymfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
16+
useSymfony\Component\DependencyInjection\ContainerInterface;
17+
useSymfony\Component\DependencyInjection\Exception\InvalidArgumentException;
18+
useSymfony\Component\DependencyInjection\TypedReference;
19+
useSymfony\Contracts\Service\Attribute\SubscribedService;
20+
useSymfony\Contracts\Service\ServiceSubscriberInterface;
21+
22+
/**
23+
* Autowires an iterator of services based on a tag name or an explicit list of key => service-type pairs.
24+
*/
25+
#[\Attribute(\Attribute::TARGET_PARAMETER)]
26+
class AutowireIteratorextends Autowire
27+
{
28+
/**
29+
* @see ServiceSubscriberInterface::getSubscribedServices()
30+
*
31+
* @param string|array<string|SubscribedService> $services A tag name or an explicit list of services
32+
* @param string|string[] $exclude A service or a list of services to exclude
33+
*/
34+
publicfunction__construct(
35+
string|array$services,
36+
string$indexAttribute =null,
37+
string$defaultIndexMethod =null,
38+
string$defaultPriorityMethod =null,
39+
string|array$exclude = [],
40+
bool$excludeSelf =true,
41+
) {
42+
if (\is_string($services)) {
43+
parent::__construct(newTaggedIteratorArgument($services,$indexAttribute,$defaultIndexMethod,false,$defaultPriorityMethod, (array)$exclude,$excludeSelf));
44+
45+
return;
46+
}
47+
48+
$references = [];
49+
50+
foreach ($servicesas$key =>$type) {
51+
$attributes = [];
52+
53+
if ($typeinstanceof SubscribedService) {
54+
$key =$type->key ??$key;
55+
$attributes =$type->attributes;
56+
$type = ($type->nullable ?'?' :'').($type->type ??thrownewInvalidArgumentException(sprintf('When "%s" is used, a type must be set.', SubscribedService::class)));
57+
}
58+
59+
if (!\is_string($type) || !preg_match('/(?(DEFINE)(?<cn>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?(DEFINE)(?<fqcn>(?&cn)(?:\\\\(?&cn))*+))^\??(?&fqcn)(?:(?:\|(?&fqcn))*+|(?:&(?&fqcn))*+)$/',$type)) {
60+
thrownewInvalidArgumentException(sprintf('"%s" is not a PHP type for key "%s".',\is_string($type) ?$type :get_debug_type($type),$key));
61+
}
62+
$optionalBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
63+
if ('?' ===$type[0]) {
64+
$type =substr($type,1);
65+
$optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
66+
}
67+
if (\is_int($name =$key)) {
68+
$key =$type;
69+
$name =null;
70+
}
71+
72+
$references[$key] =newTypedReference($type,$type,$optionalBehavior,$name,$attributes);
73+
}
74+
75+
parent::__construct(newIteratorArgument($references));
76+
}
77+
}

‎src/Symfony/Component/DependencyInjection/Attribute/AutowireLocator.php‎

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,40 @@
1111

1212
namespaceSymfony\Component\DependencyInjection\Attribute;
1313

14+
useSymfony\Component\DependencyInjection\Argument\IteratorArgument;
1415
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
15-
useSymfony\Component\DependencyInjection\ContainerInterface;
16-
useSymfony\Component\DependencyInjection\Reference;
16+
useSymfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
17+
useSymfony\Contracts\Service\Attribute\SubscribedService;
18+
useSymfony\Contracts\Service\ServiceSubscriberInterface;
1719

20+
/**
21+
* Autowires a service locator based on a tag name or an explicit list of key => service-type pairs.
22+
*/
1823
#[\Attribute(\Attribute::TARGET_PARAMETER)]
1924
class AutowireLocatorextends Autowire
2025
{
21-
publicfunction__construct(string ...$serviceIds)
22-
{
23-
$values = [];
24-
25-
foreach ($serviceIdsas$key =>$serviceId) {
26-
if ($nullable =str_starts_with($serviceId,'?')) {
27-
$serviceId =substr($serviceId,1);
28-
}
29-
30-
if (is_numeric($key)) {
31-
$key =$serviceId;
32-
}
33-
34-
$values[$key] =newReference(
35-
$serviceId,
36-
$nullable ? ContainerInterface::IGNORE_ON_INVALID_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,
37-
);
26+
/**
27+
* @see ServiceSubscriberInterface::getSubscribedServices()
28+
*
29+
* @param string|array<string|SubscribedService> $services An explicit list of services or a tag name
30+
* @param string|string[] $exclude A service or a list of services to exclude
31+
*/
32+
publicfunction__construct(
33+
string|array$services,
34+
string$indexAttribute =null,
35+
string$defaultIndexMethod =null,
36+
string$defaultPriorityMethod =null,
37+
string|array$exclude = [],
38+
bool$excludeSelf =true,
39+
) {
40+
$iterator = (newAutowireIterator($services,$indexAttribute,$defaultIndexMethod,$defaultPriorityMethod, (array)$exclude,$excludeSelf))->value;
41+
42+
if ($iteratorinstanceof TaggedIteratorArgument) {
43+
$iterator =newTaggedIteratorArgument($iterator->getTag(),$iterator->getIndexAttribute(),$iterator->getDefaultIndexMethod(),true,$iterator->getDefaultPriorityMethod(),$iterator->getExclude(),$iterator->excludeSelf());
44+
}elseif ($iteratorinstanceof IteratorArgument) {
45+
$iterator =$iterator->getValues();
3846
}
3947

40-
parent::__construct(newServiceLocatorArgument($values));
48+
parent::__construct(newServiceLocatorArgument($iterator));
4149
}
4250
}

‎src/Symfony/Component/DependencyInjection/Attribute/TaggedIterator.php‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@
1111

1212
namespaceSymfony\Component\DependencyInjection\Attribute;
1313

14-
useSymfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
15-
1614
#[\Attribute(\Attribute::TARGET_PARAMETER)]
17-
class TaggedIteratorextendsAutowire
15+
class TaggedIteratorextendsAutowireIterator
1816
{
1917
publicfunction__construct(
2018
publicstring$tag,
@@ -24,6 +22,6 @@ public function __construct(
2422
publicstring|array$exclude = [],
2523
publicbool$excludeSelf =true,
2624
) {
27-
parent::__construct(newTaggedIteratorArgument($tag,$indexAttribute,$defaultIndexMethod,false,$defaultPriorityMethod,(array)$exclude,$excludeSelf));
25+
parent::__construct($tag,$indexAttribute,$defaultIndexMethod,$defaultPriorityMethod,$exclude,$excludeSelf);
2826
}
2927
}

‎src/Symfony/Component/DependencyInjection/Attribute/TaggedLocator.php‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@
1111

1212
namespaceSymfony\Component\DependencyInjection\Attribute;
1313

14-
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
15-
useSymfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
16-
1714
#[\Attribute(\Attribute::TARGET_PARAMETER)]
18-
class TaggedLocatorextendsAutowire
15+
class TaggedLocatorextendsAutowireLocator
1916
{
2017
publicfunction__construct(
2118
publicstring$tag,
@@ -25,6 +22,6 @@ public function __construct(
2522
publicstring|array$exclude = [],
2623
publicbool$excludeSelf =true,
2724
) {
28-
parent::__construct(newServiceLocatorArgument(newTaggedIteratorArgument($tag,$indexAttribute,$defaultIndexMethod,true,$defaultPriorityMethod,(array)$exclude,$excludeSelf)));
25+
parent::__construct($tag,$indexAttribute,$defaultIndexMethod,$defaultPriorityMethod,$exclude,$excludeSelf);
2926
}
3027
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ CHANGELOG
77
* Allow using`#[Target]` with no arguments to state that a parameter must match a named autowiring alias
88
* Deprecate`ContainerAwareInterface` and`ContainerAwareTrait`, use dependency injection instead
99
* Add`defined` env var processor that returns`true` for defined and neither null nor empty env vars
10-
* Add`#[AutowireLocator]`attribute
10+
* Add`#[AutowireLocator]`and`#[AutowireIterator]` attributes
1111

1212
6.3
1313
---

‎src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,16 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
7979
$attributes = [];
8080

8181
if ($typeinstanceof SubscribedService) {
82-
$key =$type->key;
82+
$key =$type->key ??$key;
8383
$attributes =$type->attributes;
8484
$type = ($type->nullable ?'?' :'').($type->type ??thrownewInvalidArgumentException(sprintf('When "%s::getSubscribedServices()" returns "%s", a type must be set.',$class, SubscribedService::class)));
8585
}
8686

8787
if (!\is_string($type) || !preg_match('/(?(DEFINE)(?<cn>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?(DEFINE)(?<fqcn>(?&cn)(?:\\\\(?&cn))*+))^\??(?&fqcn)(?:(?:\|(?&fqcn))*+|(?:&(?&fqcn))*+)$/',$type)) {
8888
thrownewInvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.',$class,$this->currentId,$key,\is_string($type) ?$type :get_debug_type($type)));
8989
}
90-
if ($optionalBehavior ='?' ===$type[0]) {
90+
$optionalBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
91+
if ('?' ===$type[0]) {
9192
$type =substr($type,1);
9293
$optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
9394
}
@@ -120,7 +121,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
120121
$name =$this->container->has($type.' $'.$camelCaseName) ?$camelCaseName :$name;
121122
}
122123

123-
$subscriberMap[$key] =newTypedReference((string)$serviceMap[$key],$type,$optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,$name,$attributes);
124+
$subscriberMap[$key] =newTypedReference((string)$serviceMap[$key],$type,$optionalBehavior,$name,$attributes);
124125
unset($serviceMap[$key]);
125126
}
126127

‎src/Symfony/Component/DependencyInjection/Tests/Attribute/AutowireLocatorTest.php‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,33 @@
1515
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1616
useSymfony\Component\DependencyInjection\Attribute\AutowireLocator;
1717
useSymfony\Component\DependencyInjection\ContainerInterface;
18-
useSymfony\Component\DependencyInjection\Reference;
18+
useSymfony\Component\DependencyInjection\TypedReference;
1919

2020
class AutowireLocatorTestextends TestCase
2121
{
2222
publicfunctiontestSimpleLocator()
2323
{
24-
$locator =newAutowireLocator('foo','bar');
24+
$locator =newAutowireLocator(['foo','bar']);
2525

2626
$this->assertEquals(
27-
newServiceLocatorArgument(['foo' =>newReference('foo'),'bar' =>newReference('bar')]),
27+
newServiceLocatorArgument(['foo' =>newTypedReference('foo','foo'),'bar' =>newTypedReference('bar','bar')]),
2828
$locator->value,
2929
);
3030
}
3131

3232
publicfunctiontestComplexLocator()
3333
{
34-
$locator =newAutowireLocator(
34+
$locator =newAutowireLocator([
3535
'?qux',
36-
foo:'bar',
37-
bar:'?baz',
38-
);
36+
'foo' =>'bar',
37+
'bar' =>'?baz',
38+
]);
3939

4040
$this->assertEquals(
4141
newServiceLocatorArgument([
42-
'qux' =>newReference('qux', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
43-
'foo' =>newReference('bar'),
44-
'bar' =>newReference('baz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
42+
'qux' =>newTypedReference('qux','qux', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
43+
'foo' =>newTypedReference('bar','bar', name:'foo'),
44+
'bar' =>newTypedReference('baz','baz',ContainerInterface::IGNORE_ON_INVALID_REFERENCE,'bar'),
4545
]),
4646
$locator->value,
4747
);

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/AutowireLocatorConsumer.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
finalclass AutowireLocatorConsumer
1818
{
1919
publicfunction__construct(
20-
#[AutowireLocator(
20+
#[AutowireLocator([
2121
BarTagClass::class,
22-
with_key: FooTagClass::class,
23-
nullable:'?invalid',
24-
)]
22+
'with_key' => FooTagClass::class,
23+
'nullable' =>'?invalid',
24+
])]
2525
publicreadonlyContainerInterface$locator,
2626
) {
2727
}

‎src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ class WithTaggedIteratorAndTaggedLocator
676676
publicfunctionfooAction(
677677
#[TaggedIterator('foobar')]iterable$iterator,
678678
#[TaggedLocator('foobar')]ServiceLocator$locator,
679-
#[AutowireLocator('bar','baz')]ContainerInterface$container,
679+
#[AutowireLocator(['bar','baz'])]ContainerInterface$container,
680680
) {
681681
}
682682
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp