2013-03-25 39 views
8

是否可以在Symfony 2(xml configs)中動態地設置參數中的服務ID(例如,可以通過參數設置類名)?symfony2參數中的動態服務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%動態地「服務1」或「服務2」,所以所需要的實例/對象被傳遞爲了MyService級,例如在extension :: load()中通過$ container-> setParameter('dynamic_service_name','service1');

非常感謝

+0

您能否將參數添加到您提供的代碼中。您的代碼中沒有參數。 – Seer 2013-03-25 14:12:26

回答

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" 
+0

不幸的是,因爲有了這個「解決方案」,我只是將一個字符串傳遞給服務,而不是一個對象/服務的實例。 – user1826848 2013-03-25 14:06:48

+0

如果您使用php文件名嘗試它,那將無法工作...確保你使用的是類名和命名空間。再次瀏覽該文檔頁面。我會給你從我的一個服務的例子,它在YAML雖然... – Seer 2013-03-25 14:10:34

+0

當然可以通過參數動態設置類名稱,但我想設置動態服務的id – user1826848 2013-03-25 14:44:46

16

您可以使用CompilerPass:

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

,並把它添加到您的包類:

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

你的解決方案很漂亮!謝謝! :) – 2014-06-14 17:02:20

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

添加到彼得·福克斯的答案,這裏是在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標準,因此我將其替換了。

1

您可以使用parameter()函數向服務定義中讀取參數,並使用service()函數創建服務。所以,你可以創建一個動態服務

在你parameters.yml

parameters: 
     dynamic_service_name: mydynamicservice 

在您的服務。yml

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