我有一个处理某些数据并循环通过多个“处理器”进行处理的命令。代码是这样的:
image
...
在循环中,我必须为处理器分配各种依赖关系,其中一些可以自动装配。在这种情况下,我将如何使用自动装配,因为我的类名称不是静态的,而是在数组中。
Symfony版本为4.1
答案 0 :(得分:2)
在您的代码中有很多东西不是立即显而易见的,但是解决此问题的典型方法是使用“服务定位器”。 Docs。
让我们假设您有一些实现接口Processor
的服务:
界面:
interface Processor {
public function process($file): void;
}
夫妇的实现:
class Foo implements Processor
{
public function __construct(DataSetProvider $dataSet, ArchivalHashService $archivalHash, \Swift_Mailer $swift) {
// initialize properties
}
public function process($file) {
// process implementation
}
public static function getDefaultIndexName(): string
{
return 'candidateFileOne';
}
}
夫妇的实现:
class Bar implements Processor
{
public function __construct(\Swift_Mailer $swift, EntityManagerInterface $em) {
// initialize properties
}
public function process($file) {
// process implementation
}
public static function getDefaultIndexName(): string
{
return 'candidateFileTwo';
}
}
请注意,每个处理器具有完全不同的依赖性,可以直接自动连接,并且每个处理器都有一个getDefaultIndexName()
方法。
现在,我们将“标记”实现Processor
接口的所有服务:
# services.yaml
services:
# somewhere below the _defaults and the part where you make all classes in `src` available as services
_instanceof:
App\Processor:
tags:
- { name: "processor_services", default_index_method: 'getDefaultIndexName' }
注意:文档says(如果您定义了public static function getDefaultIndexName()
,则默认情况下会选中该文档)。但是我发现此目前不起作用。但是,如果您定义default_index_method
,则可以将其连接到您选择的方法。我暂时保留getDefaultIndexName
,但您可以选择自己的东西。
现在,如果您需要在控制台命令中执行此过程,例如:
use Symfony\Component\DependencyInjection\ServiceLocator;
class MyConsoleCommand
{
private ServiceLocator $locator;
public function __construct(ServiceLocator $locator)
{
$this->locator = $locator;
}
}
要注入服务定位器,您需要执行以下操作:
#services.yaml
services:
App\HandlerCollection:
arguments: [!tagged_locator { tag: 'processor_services' } ]
要从服务定位器中获取任何处理器,您将执行以下操作:
$fooProcessor = $this->locator->get('candidateFileOne');
$barProcessor = $this->locator->get('candidateFileTwo');
总结一下,基本上您需要的是:
getDefaultIndexName()
,可帮助您将文件与处理器进行匹配。您可以保留所有服务的自动连线。
注意:您可以使用抽象类而不是接口,其工作方式相同。我更喜欢使用界面,但这取决于您。
为了完整起见,here is a repo与上面的工作在Symfony 4.3上一样。