Symfony AutoWire 多个服务同一个类
Posted
技术标签:
【中文标题】Symfony AutoWire 多个服务同一个类【英文标题】:Symfony AutoWire multiple services same class 【发布时间】: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 条目。 是的,我知道,试过了,有效,但最好的代码越少! 【参考方案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;
【讨论】:
以上是关于Symfony AutoWire 多个服务同一个类的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能将此 Spring Boot 服务类注入 JUnit 测试类?预计至少有 1 个 bean 有资格作为 autowire 候选者