Symfony 4 setter 注入不能在有或没有自动装配的情况下工作

Symfony 4 setter injection not working in bundle with or without autowire

我以为我完全理解 Symfony 的自动装配行为,但肯定有一些我遗漏的东西,我希望有人可以填补空白。

开头的三个问题:

我在使用 setter 注入的包中有一个服务定义,但它似乎完全被 Symfony 忽略了,当我要求 Symfony 自动装配我的包服务时,甚至当我要求 Symfony 时从自动装配中排除服务。

我的应用程序正在使用 Symfony v4.1.3

我已将我的 Bundle 包含在我的应用程序 bundles.php 文件中。

<?php

return [
  //... core bundles,
  Acme\Symfony\AcmeCustomBundle\AcmeCustomBundle::class => ['all' => true] 
];

default Symfony 应用程序 services.yaml 文件中,我要求 Symfony 使用以下内容自动装配我的捆绑服务:

Acme\Symfony\AcmeCustomBundle\:
    resource: '../vendor/acme-symfony/custom-bundle/*'
    exclude: '../vendor/acme-symfony/custom-bundle/{Model,Tests}'

在位于 ../vendor/acme-symfony/custom-bundle/Resources/config/services.yaml 的捆绑包 services.yaml 文件中,我有以下内容:

parameters:

services:
    Acme\Symfony\AcmeCustomBundle\Search\ConfigurationReader:
      calls:
        - method: setIndex
          arguments:
            $index: '%elasticsearch.index%'
        - method: setSchema
          arguments:
            $schema: '%elasticsearch.schema%'  

参数在我的包扩展 class(扩展可配置扩展)中设置,我已经验证参数确实存在并且正在使用以下方法设置:

$container->setParameter('elasticsearch.index', $mergedConfigs['elasticsearch']['index']);
$container->setParameter('elasticsearch.schema', $mergedConfigs['elasticsearch']['schema']);

现在回到问题。 Symfony 没有执行 setter 注入,即使我告诉 Symfony 不要通过执行以下操作自动装配上述服务:

 Acme\Symfony\AcmeCustomBundle\:
    resource: '../vendor/acme-symfony/custom-bundle/*'
    exclude: '../vendor/acme-symfony/custom-bundle/{Model,Tests,Search}'

不过,当我

时,我确实让 Symfony 配置了我的服务

这样回答了我上面的第二个问题,但我不是100%确定。尽管如此,我宁愿不必使用工厂 class 来解决 Symfony 可能存在的问题,或者我不了解 setter 注入/自动装配的真正工作方式。

有人能看出我遗漏了什么吗?

首先,要共享的包中的自动装配不是最佳实践的一部分。您必须明确定义要共享的捆绑包的服务,并在 xml 中进行。

现在,话虽如此,autowire 所做的是在 class 的构造函数中连接服务,尝试自动解析它们。它不执行 setter 注入。

您需要做的是配置一个自动配置入口。在您的捆绑包扩展 class 中,您可以:

$container->registerForAutoconfiguration(ConfigurationReader::class)
    ->addMethodCall('setIndex', ['%elasticsearch.index%'])
    ->addMethodCall('setSchema', ['%elasticsearch.schema%']);

现在,这实际上是要与接口或抽象 classes 一起使用,而不是与具体实现一起使用。但是如果你想自动配置你的服务,你可以做什么。

我的建议是,如果您要重用这个包,请在 xml 中明确定义服务。自动装配适用于您的业务逻辑和服务。

如果需要,您可以自动装配其他方法(例如 Setters),只需在您的服务中使用 @required 注释即可:

/**
 * @required
 */
public function setFoo(FooInterface $foo)
{
    $this->foo = $foo;
}

Autowiring other methods