8000 [DependencyInjection] #[Autowire] attribute should have precedence ov… · symfony/symfony@c429fe5 · GitHub
[go: up one dir, main page]

Skip to content

Commit c429fe5

Browse files
committed
[DependencyInjection] #[Autowire] attribute should have precedence over bindings
1 parent aff2a1c commit c429fe5

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
1515
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1616
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
17+
use Symfony\Component\DependencyInjection\Attribute\Autowire;
1718
use Symfony\Component\DependencyInjection\Attribute\Target;
1819
use Symfony\Component\DependencyInjection\ContainerBuilder;
1920
use Symfony\Component\DependencyInjection\Definition;
@@ -185,6 +186,13 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
185186
if (\array_key_exists($parameter->name, $arguments) && '' !== $arguments[$parameter->name]) {
186187
continue;
187188
}
189+
if (
190+
$value->isAutowired()
191+
&& !$value->hasTag('container.ignore_attributes')
192+
&& $parameter->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF)
193+
) {
194+
continue;
195+
}
188196

189197
$typeHint = ltrim(ProxyHelper::exportType($parameter) ?? '', '?');
190198

src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php

+62
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Psr\Container\ContainerInterface;
1616
use Symfony\Component\Config\FileLocator;
1717
use Symfony\Component\DependencyInjection\Alias;
18+
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
1819
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1920
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
2021
use Symfony\Component\DependencyInjection\ChildDefinition;
@@ -47,6 +48,7 @@
4748
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithDefaultIndexMethodAndWithDefaultPriorityMethod;
4849
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithDefaultPriorityMethod;
4950
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithoutIndex;
51+
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerWithServiceSubscriber;
5052
use Symfony\Component\DependencyInjection\Tests\Fixtures\StaticMethodTag;
5153
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedConsumerWithExclude;
5254
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService1;
@@ -1085,6 +1087,66 @@ public function testTaggedIteratorAndLocatorWithExclude()
10851087
$this->assertTrue($locator->has(AutoconfiguredService2::class));
10861088
$this->assertFalse($locator->has(TaggedConsumerWithExclude::class));
10871089
}
1090+
1091+
public function testAutowireAttributeHasPriorityOverBindings()
1092+
{
1093+
$container = new ContainerBuilder();
1094+
$container->register(FooTagClass::class)
1095+
->setPublic(true)
1096+
->addTag('foo_bar', ['key' => 'tagged_service'])
1097+
;
1098+
$container->register(LocatorConsumerWithServiceSubscriber::class)
1099+
->setBindings([
1100+
'$locator' => new BoundArgument(new Reference('service_container'), false),
1101+
])
1102+
->setPublic(true)
1103+
->setAutowired(true)
1104+
->addTag('container.service_subscriber')
1105+
;
1106+
$container->register('subscribed_service', \stdClass::class)
1107+
->setPublic(true)
1108+
;
1109+
1110+
$container->compile();
1111+
1112+
/** @var LocatorConsumerWithServiceSubscriber $s */
1113+
$s = $container->get(LocatorConsumerWithServiceSubscriber::class);
1114+
1115+
self::assertInstanceOf(ContainerInterface::class, $subscriberLocator = $s->getContainer());
1116+
self::assertTrue($subscriberLocator->has('subscribed_service'));
1117+
self::assertNotSame($subscriberLocator, $taggedLocator = $s->getLocator());
1118+
self::assertInstanceOf(ContainerInterface::class, $taggedLocator);
1119+
self::assertTrue($taggedLocator->has('tagged_service'));
1120+
}
1121+
1122+
public function testBindingsWithAutowireAttributeAndAutowireFalse()
1123+
{
1124+
$container = new ContainerBuilder();
1125+
$container->register(FooTagClass::class)
1126+
->setPublic(true)
1127+
->addTag('foo_bar', ['key' => 'tagged_service'])
1128+
;
1129+
$container->register(LocatorConsumerWithServiceSubscriber::class)
1130+
->setBindings([
1131+
'$locator' => new BoundArgument(new Reference('service_container'), false),
1132+
])
1133+
->setPublic(true)
1134+
->setAutowired(false)
1135+
->addTag('container.service_subscriber')
1136+
;
1137+
$container->register('subscribed_service', \stdClass::class)
1138+
->setPublic(true)
1139+
;
1140+
1141+
$container->compile();
1142+
1143+
/** @var LocatorConsumerWithServiceSubscriber $s */
1144+
$s = $container->get(LocatorConsumerWithServiceSubscriber::class);
1145+
1146+
self::assertNull($s->getContainer());
1147+
self::assertInstanceOf(ContainerInterface::class, $taggedLocator = $s->getLocator());
1148+
self::assertSame($container, $taggedLocator);
1149+
}
10881150
}
10891151

10901152
class ServiceSubscriberStub implements ServiceSubscriberInterface
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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\Fixtures;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
16+
use Symfony\Contracts\Service\Attribute\Required;
17+
use Symfony\Contracts\Service\ServiceSubscriberInterface;
18+
19+
final class LocatorConsumerWithServiceSubscriber implements ServiceSubscriberInterface
20+
{
21+
private ?ContainerInterface $container = null;
22+
23+
public function __construct(
24+
#[TaggedLocator('foo_bar', indexAttribute: 'key')]
25+
private ContainerInterface $locator,
26+
) {
27+
}
28+
29+
public function getLocator(): ContainerInterface
30+
{
31+
return $this->locator;
32+
}
33+
34+
public function getContainer(): ?ContainerInterface
35+
{
36+
return $this->container;
37+
}
38+
39+
#[Required]
40+
public function setContainer(ContainerInterface $container): void
41+
{
42+
$this->container = $container;
43+
}
44+
45+
public static function getSubscribedServices(): array
46+
{
47+
return [
48+
'subscribed_service',
49+
];
50+
}
51+
}

0 commit comments

Comments
 (0)
0