Symfony AutoWire 多个服务相同 class
Symfony AutoWire multiple services same class
我正在将大型应用程序升级到 4.2
并且控制器内部的 $this->get(".....")
已弃用,应该改用 AutoWire。
我 运行 遇到了我有 2 个服务的问题,它们实际上来自同一个 class(只是不同的构造函数参数)。
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'
但我不能使用 virtual/fake class 之类的(没有现有的):
MyPseudClass: '@service.b'
你如何在自动装配模式下处理这样的情况?
我可以创建 "pseudo" classes,从基础扩展,只是为了获得不同的 classnames,但这感觉很奇怪。
从 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'
您仍然可以在 service.yml 文件中使用“@servicename”,因此按名称连接它们/这是一个示例,我将几个不同的记录器连接到服务构造函数中。
# 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:
中,但如果它们不会被重用,我认为最好保留配置更本地化)。
另一种选择是实施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;
}
}
我正在将大型应用程序升级到 4.2
并且控制器内部的 $this->get(".....")
已弃用,应该改用 AutoWire。
我 运行 遇到了我有 2 个服务的问题,它们实际上来自同一个 class(只是不同的构造函数参数)。
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'
但我不能使用 virtual/fake class 之类的(没有现有的):
MyPseudClass: '@service.b'
你如何在自动装配模式下处理这样的情况?
我可以创建 "pseudo" classes,从基础扩展,只是为了获得不同的 classnames,但这感觉很奇怪。
从 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'
您仍然可以在 service.yml 文件中使用“@servicename”,因此按名称连接它们/这是一个示例,我将几个不同的记录器连接到服务构造函数中。
# 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:
中,但如果它们不会被重用,我认为最好保留配置更本地化)。
另一种选择是实施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;
}
}