我正在将大型应用程序升级到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'
您如何在自动装配模式下处理此类情况?
我可以创建从基类扩展的“伪”类,只是为了获得不同的类名,但这感觉很奇怪。
答案 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:
中,但是如果它们不会被重用,我认为最好使配置更加本地化)。