9

Is it possible to set the service id in an argument dynamically (e.g. like a class name which could be set via parameter) in Symfony 2 (xml configs)?

The following does not work

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

the idea is to set the param %dynamic_service_name% dynamically to "service1" or "service2", so the needed instance/object is passed to myservice-class, e.g. in the Extension::load() via $container->setParameter('dynamic_service_name','service1');

Thanks a lot

4

5 回答 5

16

You can use CompilerPass:

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

and add it to your Bundle class:

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

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

FOLLOW UP:

Since Symfony 2.4 you can use Expression Language like this:

<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>
于 2013-07-26T17:37:57.107 回答
2

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

在你的parameters.yml

  parameters:
      dynamic_service_name:  mydynamicservice

在你的 services.yml

  myservice:
        class: My\Service
        arguments:['@=service(parameter("dynamic_service_name"))']
于 2017-07-12T08:55:46.643 回答
1

直接来自 symfony2 文档 ;)

<!-- 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"
于 2013-03-25T12:29:27.627 回答
0

这大致就是使用容器本身作为工厂的方式。然后,您可以将“dynamic_service_name”定义为 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>
于 2015-04-01T13:46:02.753 回答
-1

添加到彼得福克斯的答案,这是 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,所以我替换了这些。

于 2015-10-14T16:31:57.430 回答