【问题标题】:Symfony AutoWire multiple services same classSymfony AutoWire 多个服务同一个类
【发布时间】:2019-05-02 12:38:11
【问题描述】:

我正在将一个大型应用程序升级到 4.2

并且控制器内部的$this->get(".....") 已被弃用,应该使用 AutoWire。

我遇到的问题是我有 2 个服务,它们实际上来自同一个类(只是不同的构造函数参数)。

services.yml

services:
  service.a:
    class: Namespace\MyClass
    arguments: [ "argument1" ]

  service.b:
    class: Namespace\MyClass
    arguments: [ "argument2" ]

控制器:

public function demoAction() {
  $serviceA = $this->get("service.a");
  $serviceB = $this->get("service.b");
}

以及有问题的结果:

public function demoAction(MyClass $serviceA, MyClass $serviceB) {
}

我们可以使用别名来服务定义,例如:

MyClass: '@service.a'

但我不能使用虚拟/假类,例如(没有现有的):

MyPseudClass: '@service.b'

您如何在自动连线模式下处理此类情况?

我可以创建从基础扩展的“伪”类,只是为了获得不同的类名,但这感觉很奇怪。

【问题讨论】:

  • 你有一些很好的答案。我有时使用的一种方法是再创建两个类 MyClassA 和 MyClassB 都从 MyClass 扩展,否则为空。然后你可以输入提示并使用 autowire 来避免任何 services.yaml 条目。
  • 是的,我知道,试过了,有效,但最好的代码越少!

标签: symfony autowired symfony4


【解决方案1】:

从 4.2 开始,您可以定义命名的自动装配别名。这应该工作:

services:
    Namespace\MyClass $serviceA: '@service.a'
    Namespace\MyClass $serviceB: '@service.b'

在 Symfony 3.4 和 4.1 中,您可以使用绑定来代替 - 但这不太具体,因为它没有考虑类型:

services:
    _defaults:
        bind:
            $serviceA: '@service.a'
            $serviceB: '@service.b'

【讨论】:

  • thx - 这行得通,所以我采用别名方式,看起来合法且有效。在某些地方,我依赖于 services_dev.yml 更改某些服务的类的事实,因此“类型”并不稳定,所以我在这些地方使用绑定方式,绑定方式是面向未来的方式吗?还是会很快被弃用?
  • 我想你的意思是services: _defaults: bind: Namespace\MyClass $serviceA: '@service.a' Namespace\MyClass $serviceB: '@service.b':
【解决方案2】:

您仍然可以在 service.yml 文件中使用“@servicename”,因此按名称连接它们/这是一个示例,其中我将几个不同的 Logger 连接到服务构造函数中。

# App/Subscribers/WebhookLoggingListener.php file
public function __construct(
    LoggerInterface $logger, 
    LoggerInterface $mailgunLog
{ }

# services.yml
App\Subscribers\WebhookLoggingListener:
    arguments:
        $logger: "@logger"
        $mailgunLog: "@monolog.logger.mailgun"
    tags:
       - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest

您还可以将它们绑定到变量名(在 services.yaml 文件头部的 services: _defaults: 中,但如果它们不会被重用,我认为最好保持配置更加本地化)。

【讨论】:

    【解决方案3】:

    另一个选项是实现Factory Pattern。此模式将使您能够根据提供的参数创建服务。

    # services.yml
    service.a:
        class: App\MyClass
        factory: 'App\Factory\StaticMyClassFactory:createMyClass'
        arguments:
            - ['argument1']
    
    service.b:
        class: App\MyClass
        factory: 'App\Factory\StaticMyClassFactory:createMyClass'
        arguments:
            - ['argument2']
    

    你的 StaticMyClassFactory 看起来像这样

    class StaticMyClassFactory
    {  
        public static function createMyClass($argument)
        {
            // Return your class based on the argument passed
            $myClass = new MyClass($argument);
    
            return $myClass;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 2021-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多