2017-07-25 54 views
0

我需要您的建議以避免重複Symfony Dependecy Injection項目中的服務。避免依賴注入中的重複服務

該項目的目標是創建Symfony控制檯命令來管理遠程服務的對象。該服務公開API來管理對象。

遠程服務使我可以使用兩個不同的實例:生產實例和沙箱實例。

要執行的命令的例子是:

  • 創建實例用戶X
  • 創建實例的兩個實例的用戶之間的X
  • 顯示差組在兩個實例之間
  • 同步用戶

我開始創建一個類來包裝Service API並創建兩個使用同一類的兩個實例不同的認證數據:

services: 

    sandbox_instance: 
     class: APIClient 
     arguments: ["sandbox_account", "sandbox_user", "sandbox_password"] 

    prod_instance: 
     class: APIClient 
     arguments: ["prod_account", "prod_user", "prod_password"] 

但後來,我創造了一些「經理人」有不同的操作邏輯。 因此,例如,我創建了一個UserManager和一個GroupManager。 這些服務依賴於「ApiClient」服務,所以我結束了複製所有的經理,一個是生產,一個沙箱:

services: 

    .... 

    user_manager_sandbox: 
     class: UserManager 
     arguments: ['@sandbox_instance'] 

    user_manager_prod: 
     class: UserManager 
     arguments: ['@prod_instance'] 


    group_manager_sandbox: 
     class: GroupManager 
     arguments: ['@sandbox_instance'] 

    group_manager_prod: 
     class: GroupManager 
     arguments: ['@prod_instance'] 

我敢肯定,這是不使用正確的方法服務容器,但我不知道如何定義和獲取「參數」服務。

我的目標,命令代碼將撥打:

$prodUserManager = $container->get('user_manager', 'prod'); 
$sandboxUserManager = $container->get('user_manager', 'sandbox'); 

,並避免重複服務的定義。

當然,我不能簡單地將認證數據放在config參數中,並根據我想要使用的實例加載不同的配置,因爲有一些命令需要使用兩個實例(例如migration和diff命令) 。

我該如何以正確的方式做到這一點?最佳做法是什麼?

非常感謝您提前。 乾杯 利瑪竇

+1

我想你可以使用一個工廠。 $ prodUserManager = $ container-> get('user_manager_factory') - > get('prod');不管怎樣,都會變得混亂。根據你發佈的內容,我只會與重複的服務一起生活。 – Cerad

+0

如果您仍然對此感興趣,並且您嘗試過工廠方法,我想回答您。 –

回答

0

我結束了使用服務來切換環境和服務定義使用表達式語言:

環境開關類:

<?php 

class EnvSwitch 
{ 

    private $currentEnv; 

    public function getCurrentEnv(){ 
    if($this->currentEnv == null) 
     throw new \Exception('No environment selected yet.'); 
    return $this->currentEnv; 
    } 

    public function setCurrentEnv(string $env){ 
    $this->currentEnv = $env; 
    } 

    public function getCurrentEnvServiceName(){ 
    return $this->getCurrentEnv().'_instance'; 
    } 

} 

的服務定義:

services: 

    sandbox_instance: 
     class: APIClient 
     arguments: ["sandbox_account", "sandbox_user", "sandbox_password"] 

    prod_instance: 
     class: APIClient 
     arguments: ["prod_account", "prod_user", "prod_password"] 

    env_switch: 
     class: EnvSwitch 

    user_manager: 
     class: UserManager 
     arguments: ["@=service(service('env_switch').getCurrentEnvServiceName())"] 
     shared: false 

    group_manager: 
     class: GroupManager 
     arguments: ["@=service(service('env_switch').getCurrentEnvServiceName())"] 
     shared: false 

控制檯命令中的用法:

... 
$this->get('env_switch')->setCurrentEnv('sandbox'); 
$userManager = $this->get('user_manager'); 
... 

您對此解決方案有何看法? Matteo