Autowire arguments using attributes
This commit is contained in:
parent
b86aa3d068
commit
91fbc90238
@ -12,7 +12,7 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Attribute;
|
namespace Symfony\Component\DependencyInjection\Attribute;
|
||||||
|
|
||||||
#[\Attribute(\Attribute::TARGET_PARAMETER)]
|
#[\Attribute(\Attribute::TARGET_PARAMETER)]
|
||||||
class BindTaggedLocator
|
class TaggedIterator
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $tag,
|
public string $tag,
|
@ -12,7 +12,7 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Attribute;
|
namespace Symfony\Component\DependencyInjection\Attribute;
|
||||||
|
|
||||||
#[\Attribute(\Attribute::TARGET_PARAMETER)]
|
#[\Attribute(\Attribute::TARGET_PARAMETER)]
|
||||||
class BindTaggedIterator
|
class TaggedLocator
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $tag,
|
public string $tag,
|
@ -9,7 +9,7 @@ CHANGELOG
|
|||||||
* Add support for loading autoconfiguration rules via the `#[Autoconfigure]` and `#[AutoconfigureTag]` attributes on PHP 8
|
* Add support for loading autoconfiguration rules via the `#[Autoconfigure]` and `#[AutoconfigureTag]` attributes on PHP 8
|
||||||
* Add `#[AsTaggedItem]` attribute for defining the index and priority of classes found in tagged iterators/locators
|
* Add `#[AsTaggedItem]` attribute for defining the index and priority of classes found in tagged iterators/locators
|
||||||
* Add autoconfigurable attributes
|
* Add autoconfigurable attributes
|
||||||
* Add support for binding tagged iterators and locators to constructor arguments via attributes
|
* Add support for autowiring tagged iterators and locators via attributes on PHP 8
|
||||||
* Add support for per-env configuration in loaders
|
* Add support for per-env configuration in loaders
|
||||||
* Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
|
* Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration
|
||||||
* Add support an integer return value for default_index_method
|
* Add support an integer return value for default_index_method
|
||||||
|
@ -11,102 +11,46 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
|
||||||
use Symfony\Component\DependencyInjection\Attribute\BindTaggedIterator;
|
|
||||||
use Symfony\Component\DependencyInjection\Attribute\BindTaggedLocator;
|
|
||||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alexander M. Turek <me@derrabus.de>
|
* @author Alexander M. Turek <me@derrabus.de>
|
||||||
*/
|
*/
|
||||||
final class AttributeAutoconfigurationPass extends AbstractRecursivePass
|
final class AttributeAutoconfigurationPass extends AbstractRecursivePass
|
||||||
{
|
{
|
||||||
/** @var array<string, callable>|null */
|
|
||||||
private $argumentConfigurators;
|
|
||||||
|
|
||||||
public function process(ContainerBuilder $container): void
|
public function process(ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
if (80000 > \PHP_VERSION_ID) {
|
if (80000 > \PHP_VERSION_ID || !$container->getAutoconfiguredAttributes()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->argumentConfigurators = [
|
|
||||||
BindTaggedIterator::class => static function (BindTaggedIterator $attribute) {
|
|
||||||
return new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute);
|
|
||||||
},
|
|
||||||
BindTaggedLocator::class => static function (BindTaggedLocator $attribute) {
|
|
||||||
return new ServiceLocatorArgument(new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute));
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
parent::process($container);
|
parent::process($container);
|
||||||
|
|
||||||
$this->argumentConfigurators = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function processValue($value, bool $isRoot = false)
|
protected function processValue($value, bool $isRoot = false)
|
||||||
{
|
{
|
||||||
if ($value instanceof Definition
|
if (!$value instanceof Definition
|
||||||
&& $value->isAutoconfigured()
|
|| !$value->isAutoconfigured()
|
||||||
&& !$value->isAbstract()
|
|| $value->isAbstract()
|
||||||
&& !$value->hasTag('container.ignore_attributes')
|
|| $value->hasTag('container.ignore_attributes')
|
||||||
|
|| !($reflector = $this->container->getReflectionClass($value->getClass(), false))
|
||||||
) {
|
) {
|
||||||
$value = $this->processDefinition($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::processValue($value, $isRoot);
|
return parent::processValue($value, $isRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function processDefinition(Definition $definition): Definition
|
|
||||||
{
|
|
||||||
if (!$reflector = $this->container->getReflectionClass($definition->getClass(), false)) {
|
|
||||||
return $definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
$autoconfiguredAttributes = $this->container->getAutoconfiguredAttributes();
|
$autoconfiguredAttributes = $this->container->getAutoconfiguredAttributes();
|
||||||
|
$instanceof = $value->getInstanceofConditionals();
|
||||||
$instanceof = $definition->getInstanceofConditionals();
|
|
||||||
$conditionals = $instanceof[$reflector->getName()] ?? new ChildDefinition('');
|
$conditionals = $instanceof[$reflector->getName()] ?? new ChildDefinition('');
|
||||||
foreach ($reflector->getAttributes() as $attribute) {
|
foreach ($reflector->getAttributes() as $attribute) {
|
||||||
if ($configurator = $autoconfiguredAttributes[$attribute->getName()] ?? null) {
|
if ($configurator = $autoconfiguredAttributes[$attribute->getName()] ?? null) {
|
||||||
$configurator($conditionals, $attribute->newInstance(), $reflector);
|
$configurator($conditionals, $attribute->newInstance(), $reflector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($constructor = $this->getConstructor($definition, false)) {
|
|
||||||
$definition = $this->bindArguments($definition, $constructor);
|
|
||||||
}
|
|
||||||
|
|
||||||
$instanceof[$reflector->getName()] = $conditionals;
|
$instanceof[$reflector->getName()] = $conditionals;
|
||||||
$definition->setInstanceofConditionals($instanceof);
|
$value->setInstanceofConditionals($instanceof);
|
||||||
|
|
||||||
return $definition;
|
return parent::processValue($value, $isRoot);
|
||||||
}
|
|
||||||
|
|
||||||
private function bindArguments(Definition $definition, \ReflectionFunctionAbstract $constructor): Definition
|
|
||||||
{
|
|
||||||
$bindings = $definition->getBindings();
|
|
||||||
foreach ($constructor->getParameters() as $reflectionParameter) {
|
|
||||||
$argument = null;
|
|
||||||
foreach ($reflectionParameter->getAttributes() as $attribute) {
|
|
||||||
if (!$configurator = $this->argumentConfigurators[$attribute->getName()] ?? null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($argument) {
|
|
||||||
throw new LogicException(sprintf('Cannot autoconfigure argument "$%s": More than one autoconfigurable attribute found.', $reflectionParameter->getName()));
|
|
||||||
}
|
|
||||||
$argument = $configurator($attribute->newInstance());
|
|
||||||
}
|
|
||||||
if ($argument) {
|
|
||||||
$bindings['$'.$reflectionParameter->getName()] = new BoundArgument($argument);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $definition->setBindings($bindings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||||
|
|
||||||
use Symfony\Component\Config\Resource\ClassExistenceResource;
|
use Symfony\Component\Config\Resource\ClassExistenceResource;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
|
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
|
||||||
@ -123,7 +127,8 @@ class AutowirePass extends AbstractRecursivePass
|
|||||||
array_unshift($this->methodCalls, [$constructor, $value->getArguments()]);
|
array_unshift($this->methodCalls, [$constructor, $value->getArguments()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot);
|
$checkAttributes = 80000 <= \PHP_VERSION_ID && !$value->hasTag('container.ignore_attributes');
|
||||||
|
$this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot, $checkAttributes);
|
||||||
|
|
||||||
if ($constructor) {
|
if ($constructor) {
|
||||||
[, $arguments] = array_shift($this->methodCalls);
|
[, $arguments] = array_shift($this->methodCalls);
|
||||||
@ -140,7 +145,7 @@ class AutowirePass extends AbstractRecursivePass
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot): array
|
private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot, bool $checkAttributes): array
|
||||||
{
|
{
|
||||||
$this->decoratedId = null;
|
$this->decoratedId = null;
|
||||||
$this->decoratedClass = null;
|
$this->decoratedClass = null;
|
||||||
@ -168,7 +173,7 @@ class AutowirePass extends AbstractRecursivePass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$arguments = $this->autowireMethod($reflectionMethod, $arguments);
|
$arguments = $this->autowireMethod($reflectionMethod, $arguments, $checkAttributes);
|
||||||
|
|
||||||
if ($arguments !== $call[1]) {
|
if ($arguments !== $call[1]) {
|
||||||
$this->methodCalls[$i][1] = $arguments;
|
$this->methodCalls[$i][1] = $arguments;
|
||||||
@ -185,7 +190,7 @@ class AutowirePass extends AbstractRecursivePass
|
|||||||
*
|
*
|
||||||
* @throws AutowiringFailedException
|
* @throws AutowiringFailedException
|
||||||
*/
|
*/
|
||||||
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments): array
|
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments, bool $checkAttributes): array
|
||||||
{
|
{
|
||||||
$class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
|
$class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
|
||||||
$method = $reflectionMethod->name;
|
$method = $reflectionMethod->name;
|
||||||
@ -201,6 +206,26 @@ class AutowirePass extends AbstractRecursivePass
|
|||||||
|
|
||||||
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
|
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
|
||||||
|
|
||||||
|
if ($checkAttributes) {
|
||||||
|
foreach ($parameter->getAttributes() as $attribute) {
|
||||||
|
if (TaggedIterator::class === $attribute->getName()) {
|
||||||
|
$attribute = $attribute->newInstance();
|
||||||
|
$arguments[$index] = new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TaggedLocator::class === $attribute->getName()) {
|
||||||
|
$attribute = $attribute->newInstance();
|
||||||
|
$arguments[$index] = new ServiceLocatorArgument(new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('' !== ($arguments[$index] ?? '')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!$type) {
|
if (!$type) {
|
||||||
if (isset($arguments[$index])) {
|
if (isset($arguments[$index])) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -62,10 +62,10 @@ class PassConfig
|
|||||||
new AutowireRequiredMethodsPass(),
|
new AutowireRequiredMethodsPass(),
|
||||||
new AutowireRequiredPropertiesPass(),
|
new AutowireRequiredPropertiesPass(),
|
||||||
new ResolveBindingsPass(),
|
new ResolveBindingsPass(),
|
||||||
new ServiceLocatorTagPass(),
|
|
||||||
new DecoratorServicePass(),
|
new DecoratorServicePass(),
|
||||||
new CheckDefinitionValidityPass(),
|
new CheckDefinitionValidityPass(),
|
||||||
new AutowirePass(false),
|
new AutowirePass(false),
|
||||||
|
new ServiceLocatorTagPass(),
|
||||||
new ResolveTaggedIteratorArgumentPass(),
|
new ResolveTaggedIteratorArgumentPass(),
|
||||||
new ResolveServiceSubscribersPass(),
|
new ResolveServiceSubscribersPass(),
|
||||||
new ResolveReferencesToAliasesPass(),
|
new ResolveReferencesToAliasesPass(),
|
||||||
|
@ -20,7 +20,6 @@ use Symfony\Component\DependencyInjection\ChildDefinition;
|
|||||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
|
||||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||||
@ -33,7 +32,6 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\IteratorConsumer;
|
|||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumer;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumer;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerConsumer;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerConsumer;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerFactory;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\LocatorConsumerFactory;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\MultipleArgumentBindings;
|
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService1;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService1;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService2;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService2;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService3;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService3;
|
||||||
@ -338,7 +336,7 @@ class IntegrationTest extends TestCase
|
|||||||
->addTag('foo_bar', ['foo' => 'foo'])
|
->addTag('foo_bar', ['foo' => 'foo'])
|
||||||
;
|
;
|
||||||
$container->register(IteratorConsumer::class)
|
$container->register(IteratorConsumer::class)
|
||||||
->setAutoconfigured(true)
|
->setAutowired(true)
|
||||||
->setPublic(true)
|
->setPublic(true)
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -391,7 +389,7 @@ class IntegrationTest extends TestCase
|
|||||||
->addTag('foo_bar', ['foo' => 'foo'])
|
->addTag('foo_bar', ['foo' => 'foo'])
|
||||||
;
|
;
|
||||||
$container->register(LocatorConsumer::class)
|
$container->register(LocatorConsumer::class)
|
||||||
->setAutoconfigured(true)
|
->setAutowired(true)
|
||||||
->setPublic(true)
|
->setPublic(true)
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -419,7 +417,7 @@ class IntegrationTest extends TestCase
|
|||||||
->setPublic(true)
|
->setPublic(true)
|
||||||
->setArguments([
|
->setArguments([
|
||||||
(new Definition(LocatorConsumer::class))
|
(new Definition(LocatorConsumer::class))
|
||||||
->setAutoconfigured(true),
|
->setAutowired(true),
|
||||||
])
|
])
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -445,7 +443,7 @@ class IntegrationTest extends TestCase
|
|||||||
$container->register(LocatorConsumerFactory::class);
|
$container->register(LocatorConsumerFactory::class);
|
||||||
$container->register(LocatorConsumer::class)
|
$container->register(LocatorConsumer::class)
|
||||||
->setPublic(true)
|
->setPublic(true)
|
||||||
->setAutoconfigured(true)
|
->setAutowired(true)
|
||||||
->setFactory(new Reference(LocatorConsumerFactory::class))
|
->setFactory(new Reference(LocatorConsumerFactory::class))
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -458,22 +456,6 @@ class IntegrationTest extends TestCase
|
|||||||
self::assertSame($container->get(FooTagClass::class), $locator->get('my_service'));
|
self::assertSame($container->get(FooTagClass::class), $locator->get('my_service'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires PHP 8
|
|
||||||
*/
|
|
||||||
public function testMultipleArgumentBindings()
|
|
||||||
{
|
|
||||||
$container = new ContainerBuilder();
|
|
||||||
$container->register(MultipleArgumentBindings::class)
|
|
||||||
->setPublic(true)
|
|
||||||
->setAutoconfigured(true)
|
|
||||||
;
|
|
||||||
|
|
||||||
$this->expectException(LogicException::class);
|
|
||||||
$this->expectExceptionMessage('Cannot autoconfigure argument "$collection": More than one autoconfigurable attribute found.');
|
|
||||||
$container->compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testTaggedServiceWithDefaultPriorityMethod()
|
public function testTaggedServiceWithDefaultPriorityMethod()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Attribute\BindTaggedIterator;
|
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
|
||||||
|
|
||||||
final class IteratorConsumer
|
final class IteratorConsumer
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[BindTaggedIterator('foo_bar', indexAttribute: 'foo')]
|
#[TaggedIterator('foo_bar', indexAttribute: 'foo')]
|
||||||
private iterable $param,
|
private iterable $param,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||||
|
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Symfony\Component\DependencyInjection\Attribute\BindTaggedLocator;
|
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
|
||||||
|
|
||||||
final class LocatorConsumer
|
final class LocatorConsumer
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[BindTaggedLocator('foo_bar', indexAttribute: 'foo')]
|
#[TaggedLocator('foo_bar', indexAttribute: 'foo')]
|
||||||
private ContainerInterface $locator,
|
private ContainerInterface $locator,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||||
|
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Symfony\Component\DependencyInjection\Attribute\BindTaggedLocator;
|
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
|
||||||
|
|
||||||
final class LocatorConsumerFactory
|
final class LocatorConsumerFactory
|
||||||
{
|
{
|
||||||
public function __invoke(
|
public function __invoke(
|
||||||
#[BindTaggedLocator('foo_bar', indexAttribute: 'key')]
|
#[TaggedLocator('foo_bar', indexAttribute: 'key')]
|
||||||
ContainerInterface $locator
|
ContainerInterface $locator
|
||||||
): LocatorConsumer {
|
): LocatorConsumer {
|
||||||
return new LocatorConsumer($locator);
|
return new LocatorConsumer($locator);
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Attribute\BindTaggedIterator;
|
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
|
||||||
use Symfony\Component\DependencyInjection\Attribute\BindTaggedLocator;
|
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
|
||||||
|
|
||||||
final class MultipleArgumentBindings
|
final class MultipleArgumentBindings
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[BindTaggedIterator('my_tag'), BindTaggedLocator('another_tag')]
|
#[TaggedIterator('my_tag'), TaggedLocator('another_tag')]
|
||||||
object $collection
|
object $collection
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ class ProjectServiceContainer extends Container
|
|||||||
return [
|
return [
|
||||||
'.service_locator.DlIAmAe' => true,
|
'.service_locator.DlIAmAe' => true,
|
||||||
'.service_locator.DlIAmAe.foo_service' => true,
|
'.service_locator.DlIAmAe.foo_service' => true,
|
||||||
|
'.service_locator.t5IGRMW' => true,
|
||||||
'Psr\\Container\\ContainerInterface' => true,
|
'Psr\\Container\\ContainerInterface' => true,
|
||||||
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
||||||
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true,
|
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true,
|
||||||
|
Reference in New Issue
Block a user