【问题标题】:Symfony 4 setter injection not working in bundle with or without autowireSymfony 4 setter 注入在有或没有自动装配的情况下都不能工作
【发布时间】:2019-01-12 05:12:24
【问题描述】:

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

三个问题开始:

  • 主应用程序与捆绑软件中的 Symfony 自动装配行为是否存在差异?
  • 如果您要求 Symfony 自动装配捆绑服务,它会完全忽略捆绑services.yaml 文件中的服务定义吗?
  • Symfony 4 中的 setter 注入功能是否存在已知问题?

我在使用 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%'  

参数是在我的捆绑扩展类(扩展可配置扩展)中设置的,并且我已经验证了这些参数确实存在并且正在使用以下方法进行设置:

$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% 确定的。尽管如此,我宁愿不必使用工厂类来解决 Symfony 可能存在的问题,或者我对 setter 注入/自动装配的真正工作原理缺乏了解。

谁能看到我遗漏的明显东西?

【问题讨论】:

    标签: symfony dependency-injection factory autowired symfony4


    【解决方案1】:

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

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

    Autowiring other methods

    【讨论】:

    • 您应该将此标记为正确答案@onetimeengineer
    • @MatíasNavarroCarter 刚刚看到这个。这是一个有用的提示,但我倾向于不使用 Symfony 的注释来触发功能,所以我仍然认为你的答案对我来说是正确的。
    • 我刚刚看到了那个答案,它似乎解决了我在使用不使用 setter 的编译器通行证时遇到的问题。这个注释强制使用的 Symfony 配置是否有问题。
    • @SelaYair 你可以看看 Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass
    【解决方案2】:

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

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

    您需要做的是配置一个自动配置条目。在您的捆绑扩展类中,您可以执行以下操作:

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

    现在,这实际上是用于接口或抽象类,而不是用于具体实现。但是,如果您想自动配置您的服务,您可以做什么。

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

    【讨论】:

    • 很高兴知道自动装配不会进行 setter 注入,如果那是在官方文档中,我一定错过了。我的捆绑包是私有的,核心功能不会在我的应用程序中改变,并且我已经为任何需要的东西公开了配置,所以为了方便起见,我尽可能地自动装配(但我知道最佳实践!)我用过尽管我的注入器是一项服务,但控制器中记录器注入的“注册自动配置”概念。知道我可以在扩展中做到这一点很有用。您为什么建议在 xml 而不是 yaml 中定义服务?
    • 更好的自动补全并避免恼人的 yaml PHP 风暴问题
    • 另外,更短的服务定义
    • 这些听起来像是正当的理由,尽管我个人一直更喜欢 yaml 而不是 xml。时间会证明我是否可以摆脱它!
    • 我确实认为 yaml 更容易理解。
    猜你喜欢
    • 1970-01-01
    • 2018-01-10
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 2019-05-23
    • 2016-04-08
    • 1970-01-01
    相关资源
    最近更新 更多