【问题标题】:Symfony dependency injection inject all classes of a type as parametersSymfony 依赖注入注入一个类型的所有类作为参数
【发布时间】:2019-06-01 14:52:38
【问题描述】:

如何告诉 DI 容器将某种类型的所有服务注入另一个服务?我想避免必须手动注册所有这些服务作为参数。

有什么方法可以自动执行此操作?

class A {

    /**
     * @var ISomeInterface[]
     */
    private $implementations;


    public function __construct(ISomeInterface ...$implementations)
    {
        $this->implementations = $implementations;
    }

}

interface ISomeInterface {}

【问题讨论】:

  • 你使用的是哪个版本的 Symfony?
  • 一种方法是使用Service Locator
  • @Domagoj 最新,所以 4.2
  • @Elwhis 在 Symfony 4.2 中,这是在 Kernel::configureContainer() 中完成的。在那里您可以访问ContainerBuilder,并且可以轻松地将您需要的服务注入到您的服务中。我将在下面发布示例。

标签: php symfony dependency-injection


【解决方案1】:

这可以给你一个大致的想法。它更像是一个伪代码,所以不要复制和粘贴它。 Symfony 允许您通过 ContainerBuilder 为您的服务自定义 DI - 在 3.4 中,我们在 *Extension 类中进行。在您的应用程序中,您可以在任何可以访问容器构建器的地方执行此操作。如果您知道需要注入哪些服务,则可以将它们作为参考,如果不知道,则可以遍历定义并找到符合您的条件的服务,即所需的接口。

// Symfony 3.4

- `*Extension.php` class, usually found in DependencyInjection folder of a bundle

class BundleExtension extends Extension
{
    /**
     * @param array $configs
     * @param ContainerBuilder $container
     * @throws \Exception
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); // Your services
                $loader->load('services.yml');

                $configuration = new Configuration();
                $config = $this->processConfiguration($configuration, $configs);

        $implementations = [];

         // Get your implementations

        $implementations[] = ...;


        // You can either loop through config, get them as references (new Reference() ...), compare to interface predicate

        $aService = (new Definition(A:class)) // This is the crucial part
                        ->setArgument(0, $implementations);

        $container->setDefinition(A::class, $aService);

    }
}

您可以使用$container->setArguments([/*your arguments*/]) 向您的服务注入参数。

// Symfony 4.2

// Kernel.php ...
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
    {
        $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
        $container->setParameter('container.dumper.inline_class_loader', true);
        $confDir = $this->getProjectDir().'/config';


        $arguments = [];
        $services = [1, '2', 3, 4, 'def', 'abc']; // Your services

        foreach ($services as $item) {
            if (gettype($item) === 'string') { // Check if they pass your criteria, this is just an example
                $arguments[] = $item;
            }
        }

        $aService = (new Definition(A::class, $arguments)); // Service definition
        $container->setDefinition(A::class, $aService); // Inject it to a container

        $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
        $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
        $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
        $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
    }

【讨论】:

  • 感谢您的回答,稍后再试,如果可行,请接受答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 2014-09-23
  • 2016-03-23
  • 1970-01-01
相关资源
最近更新 更多