gpt4 book ai didi

php - Symfony 3 服务依赖于未知数量的另一项服务。如何实现?

转载 作者:搜寻专家 更新时间:2023-10-31 21:52:20 24 4
gpt4 key购买 nike

我是 Symfony 的新手,但对 PHP 很有经验。假设我有一项服务需要未知数量的另一项服务。注入(inject)它没有意义(我会注入(inject)多少)。我可以使用 ContainerAwareInterfaceContainerAwareTrait 但我读到那是 not a good way .

稍微做作的例子:

class ProcessBuilder {
private $allCommands = [];

public function build(array $config){
foreach ($config => $command){
$this->allCommands[] = $this->getContainer()->get('app.worker.command')->init($command);
}
}
}

在我获得 ProcessBuilder 服务时,我不知道 $config 数组中将有多少项传递给 build( )。由于 Command 类(app.worker.command 服务)的工作方式,它们无法共享单个实例。

最好的方法是什么?还是我需要走 ContainerAware* 路线?

我希望这是有道理的,感谢您的帮助。很抱歉,如果之前有人问过这个问题,但我有一个很好的谷歌,但没有想出任何东西。

最佳答案

您的方向是正确的。现在只缺少正确的位置。

要收集某种类型的服务,我们需要先行一步。依赖注入(inject)容器编译(这就是EventSubscriber类型或Voter类型的服务被Symfony收集的方式。)

您可以使用 Extension 注册服务,并使用 CompilerPass 以任何方式操作它们

例子

这里是 example how to collect all services of type A, and add them to service of type B with setter .

您在 Compiler Pass 中的案例

如果我们将您的代码转换为编译器阶段,它将如下所示:

ProcessBuilder.php

class ProcessBuilder
{
/**
* @var CommandInterface[]
*/
private $allCommands = [];

public function addCommand(CommandInterface $command)
{
$this->allCommands[] = $command
}
}

AddCommandsToProcessBuilderCompilerPass.php

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

final class AddCommandsToProcessBuilderCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $containerBuilder): void
{
# using Symfony 3.3+ class name, you can use string name as well
$processBuilderDefinition = $this->containerBuilder->getDefinition(ProcessBuilder::class);

foreach ($this->containerBuilder->getDefinitions() as $serviceName => $definition) {
if (is_subclass_of($definition->getClass(), CommandInterface::class)) {
$processBuilderDefinition->addMethodCall('addCommand', [new Reference($serviceName)]);
}
}
}
}

AppBundle.php

use Symfony\Component\HttpKernel\Bundle\Bundle;

final class AppBundle extends Bundle
{
public function build(ContainerBuilder $containerBuilder): void
{
$containerBuilder->addCompilerPass(new AddCommandsToProcessBuilderCompilerPass);
}
}

并将您的包添加到 AppKernel.php:

final class AppKernel extends Kernel
{
public function registerBundles()
{
bundles = [];
$bundles[] = new AppBundle;
}
}

这是在 Symfony 中以干净的方式完成所需工作的完整过程。

关于php - Symfony 3 服务依赖于未知数量的另一项服务。如何实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39307178/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com