Symfony2 服务容器 : Inject array of services parameter as an argument to another service using XML

标签 symfony

我有一个参数应该代表我的 services.xml 中的服务数组文件:

<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>

现在我想将此集合作为服务数组注入(inject)另一个服务:
<services>
    <service id="notifications_decorator" class="\NotificationsDecorator">
        <argument>%decorators.all%</argument>
    </service>
</services>

但它不起作用。无法理解为什么。我错过了什么?

最佳答案

因此,您注入(inject)的参数数组没有服务数组。您可以通过以下方式逐个注入(inject)服务:

<services>
    <service id="notifications_decorator" class="\NotificationsDecorator">
        <argument type="service" id="decorator1"/>
        <argument type="service" id="decorator2"/>
        <argument type="service" id="decorator3"/>
    </service>
</services>

或者(我认为更好的方式)tag decorators服务并将它们注入(inject) notifications_decorator在编译过程中。

更新:使用标记服务

在您的情况下,您必须像这样修改您的服务:
<services>
    <service id="decorator1" class="\FirstDecorator">
        <tag name="acme_decorator" />
    </service>
    <service id="decorator2" class="\SecondDecorator">
        <tag name="acme_decorator" />
    </service>
    <service id="decorator3" class="\ThirdDecorator">
        <tag name="acme_decorator" />
    </service>
</services>

另外,您应该删除 decorators.all参数来自 <parameters>部分。接下来,您必须添加诸如addDectorator之类的东西\NotificationsDecorator 的函数:
class NotificationsDecorator
{
    private $decorators = array();

    public function addDecorator($decorator)
    {
        $this->decorators[] = $decorator;
    }
    // more code
}

如果你为decorator写一些接口(interface)就好了。的并将其添加为 $decorator 的类型对于 addDecorator功能。

接下来,您必须编写自己的编译器通行证并询问他们有关标记服务的信息,并将此服务添加到另一个服务(类似于 doc):
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;

class DecoratorCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('notifications_decorator')) {
            return;
        }

        $definition = $container->getDefinition('notifications_decorator');
        $taggedServices = $container->findTaggedServiceIds('acme_decorator');

        foreach ($taggedServices as $id => $attributes) {
            $definition->addMethodCall(
                'addDecorator',
                array(new Reference($id))
            );
        }
    }
}

最后,您应该添加您的 DecoratorCompilerPassCompiler在您的捆绑包类中,例如:
class AcmeDemoBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);

        $container->addCompilerPass(new DecoratorCompilerPass());
    }
}

祝你好运!

关于Symfony2 服务容器 : Inject array of services parameter as an argument to another service using XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18629333/

相关文章:

php - 为什么我不能像服务一样获得 Symfony Finder?

symfony - 使用 Monolog 在 Symfony2 中记录 PHP fatal error

symfony - 使用 Doctrine 和 Symfony2 进行数据库搜索

PHP/Symfony2 表单复选框字段

symfony - DQL - 从日期时间格式中提取年份

php - egyg33k Bundle ,从 ajax 调用生成 csv

php - 尝试使用 SwiftMailer : Connection could not be established with host smtp. gmail.com [#0] 通过 Symfony 2 发送电子邮件

jquery - Bootstrap 弹出窗口中的 Ajax

symfony - 预期的已知函数,得到 '...TimeDiffFunction not found in ....Doctrine\ORM\Query\Parser.php

javascript - 如何在 Symfony 上显示日期选择器?