Symfony AutoWire多个服务属于同一类

时间:2018-11-30 10:55:28

标签: symfony autowired symfony4

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

,不赞成使用控制器内部的$this->get("....."),而应该使用AutoWire。

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

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'

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

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

3 个答案:

答案 0 :(得分:8)

从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'

答案 1 :(得分:1)

另一个选择是实现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;
    }
}

答案 2 :(得分:0)

您仍然可以在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:中,但是如果它们不会被重用,我认为最好使配置更加本地化)。