'Symfony2 service container: Inject array of services parameter as an argument to another service using XML
I have a parameter which should represent array of services in my services.xml file:
<parameters>
<parameter key="decorators.all" type="collection">
<parameter type="service" id="decorator1" />
<parameter type="service" id="decorator2" />
<parameter type="service" id="decorator3" />
</parameter>
</parameters>
<services>
<service id="decorator1" class="\FirstDecorator" />
<service id="decorator2" class="\SecondDecorator" />
<service id="decorator3" class="\ThirdDecorator" />
</services>
Now I want to inject this collection to another service as an array of services:
<services>
<service id="notifications_decorator" class="\NotificationsDecorator">
<argument>%decorators.all%</argument>
</service>
</services>
But it doesn't work. Can't understand why. What am I missing?
Solution 1:[1]
Little bit different approach with tagged services (or whatever you need) and CompilerPassInterface using array of services instead of method calls.
Here are the differences from @NHG answer:
<!-- Service definition (factory in my case) -->
<service id="example.factory" class="My\Example\SelectorFactory">
<argument type="collection" /> <!-- list of services to be inserted by compiler pass -->
</service>
CompilerPass:
/*
* Used to build up factory with array of tagged services definition
*/
class ExampleCompilerPass implements CompilerPassInterface
{
const SELECTOR_TAG = 'tagged_service';
public function process(ContainerBuilder $container)
{
$selectorFactory = $container->getDefinition('example.factory');
$selectors = [];
foreach ($container->findTaggedServiceIds(self::SELECTOR_TAG) as $selectorId => $tags) {
$selectors[] = $container->getDefinition($selectorId);
}
$selectorFactory->replaceArgument(0, $selectors);
}
}
Solution 2:[2]
in yaml you can do:
app.example_conditions:
class: AppBundle\Example\Conditions
arguments:
[[ "@app.example_condition_1", "@app.example_condition_2", "@app.example_condition_3", "@app.example_condition_4" ]]
and in AppBundle\Example\Conditions you receive the array...
Solution 3:[3]
Symfony 5.3+ and php 8.0+
class NotificationsDecorator
{
private $decorators;
public function __construct(
#[TaggedIterator('app.notifications_decorators')] iterable $decorators
) {
$this->decorators = $decorators;
}
}
#[Autoconfigure(tags: ['app.notifications_decorators'])]
interface DecoratorInterface
{
}
class FirstDecorator implements DecoratorInterface
{
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | mente |
| Solution 2 | rrubiorr81 |
| Solution 3 | Artem |
