避免依赖注入中的重复服务

时间:2017-07-25 10:43:22

标签: web-services symfony dependency-injection console

我需要您的建议,以避免在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');

并避免重复服务的定义。

当然,我不能简单地将身份验证数据放在配置参数中,并根据我想要使用的实例加载不同的配置,因为有些命令我需要处理这两个实例(例如,migration和diff命令)。

我怎样才能以正确的方式做到这一点?什么是最佳做法?

非常感谢您提前。 干杯 利玛

1 个答案:

答案 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');
...

您对此解决方案有何看法? 利玛