symfony2中参数中的动态服务ID?

时间:2013-03-25 12:26:46

标签: symfony config

是否可以在Symfony 2(xml configs)中动态设置参数中的服务ID(例如,可以通过参数设置的类名)?

以下不起作用

<service id="myservice" class="myservice.php">
    <argument type="service" id="%dynamic_service_name%" />
</service>

<service id="service1" class="foobar\service1" />
<service id="service2" class="foobar\service1" />

的想法是将param%dynamic_service_name%动态设置为“service1”或“service2”,以便将所需的实例/对象传递给myservice-class,例如:在Extension :: load()中通过$ container-&gt; setParameter('dynamic_service_name','service1');

非常感谢

5 个答案:

答案 0 :(得分:16)

您可以使用CompilerPass:

class DynamicServiceCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $container->getDefinition('myservice')
            ->setArguments(array(new Reference($container->getParameter('dynamic_service_name'))));
    }
}

并将其添加到Bundle类:

public function build(ContainerBuilder $container)
{
    parent::build($container);

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

关注

从Symfony 2.4开始,您可以像这样使用Expression Language

<services>
    <service id="myservice" class="My\Service">
        <argument type="expression">service(container.hasParameter('dynamic_service_name') ? parameter('dynamic_service_name') : 'default_service_name')</argument>
    </service>
</services>

答案 1 :(得分:2)

您可以使用parameter()功能将参数读入服务定义,并使用service()功能创建服务。所以你可以创建一个动态服务

在你的parameters.yml

  parameters:
      dynamic_service_name:  mydynamicservice

在您的services.yml

  myservice:
        class: My\Service
        arguments:['@=service(parameter("dynamic_service_name"))']

答案 2 :(得分:1)

直接来自symfony2 docs;)

<!-- app/config/config.xml -->
<parameters>
    <parameter key="my_mailer.class">Acme\HelloBundle\Mailer</parameter>
    <parameter key="my_mailer.transport">sendmail</parameter>
</parameters>

<services>
    <service id="my_mailer" class="%my_mailer.class%">
        <argument>%my_mailer.transport%</argument>
    </service>
</services>

这就是你要追求的吗?

http://symfony.com/doc/current/book/service_container.html#service-parameters

编辑:

这是我的一项服务,使用参数。但是,它在YAML中。这很好用。正如您所看到的,它在类参数中使用了类名和命名空间。

parameters:
    seer_ukd_wright_gallery.gallery_helper.class: SeerUK\DWright\GalleryBundle\DependencyInjection\GalleryHelper

services:
    seer_ukd_wright_gallery.gallery_helper:
        class: %seer_ukd_wright_gallery.gallery_helper.class%
        arguments:
            em: "@doctrine.orm.entity_manager"

答案 3 :(得分:0)

这大致是如何使用容器本身作为工厂来完成的。然后,您可以定义&#39; dynamic_service_name&#39;作为service1或service2,它将加载该服务。 (工厂的XML在2.6中略有不同,但应该仍然相同)

<service id="service1" class="foobar\service1" />
<service id="service2" class="foobar\service1" />

<service id="some.service" class="foobar\service1"
             factory-service="service_container"
             factory-method="get">
        <argument>%dynamic_service_name%</argument>
    </service>

<service id="myservice" class="myservice.php">
    <argument type="service" id="some.service" />
</service>

答案 4 :(得分:-1)

加入彼得福克斯&#39;回答,这里是YAML中的等价物:

some.service:
    class: Foobar\Service1
    factory_service: service_container
    factory_method: get
    arguments:
        - %dynamic_service_name%
myservice:
    class: MyService
    arguments:
        - @some.service

如何指定两个服务的类有两个小的差异。我不熟悉使用文件名作为类,foobar\service1也不符合PSR,所以我替换了这些。