【问题标题】:Autowire not working in Symfony's Dependency Injection componentAutowire 在 Symfony 的依赖注入组件中不起作用
【发布时间】:2018-04-03 07:24:11
【问题描述】:

我在我的自定义 PHP 项目中使用 Symfony 的依赖注入组件版本 3.4。我的项目在 PHP 5.6 上运行

"symfony/dependency-injection": "^3.4"

我已经定义了我的 services.yaml 文件以包含以下服务定义

logger:
  class: Monolog\Logger
  arguments: ["application"]
  autowire: true
  public: true

Monolog\Logger: '@logger'

plugin_context:
  class: MyProject\PluginContext
  autowire: true
  public: true

我可以确认自动加载正在工作并且两个类的实例都存在于定义中,但是 Logger 类没有在 PluginContext 构造函数中自动装配。该类在以下代码中定义

use Monolog\Logger;

class PluginContext
{
    private $logger;
    function __construct(Logger $logger) {
        $this->logger = $logger;
    }
}

以下代码运行时,PHP抛出异常

$container->get("plugin_context");

Catchable fatal error: Argument 1 passed to MyProject\PluginContext::__construct() must be an instance of Monolog\Logger, none given

【问题讨论】:

  • 缺少arguments: ["Monolog\Logger"]plugin_context:?似乎您的构造函数需要记录器依赖项,但未在插件内容的参数中定义
  • @Smaine 下面关于针对 LoggerInterface 的类型提示的回答是正确的。如果您打算使用 autowire,那么您需要对其工作原理有相当深入的了解,这意味着阅读和理解 docs。并学习使用诸如“bin/console debug:container --show-private | grep logger”之类的命令来查看可用的服务和别名。

标签: php symfony dependency-injection autowired


【解决方案1】:

更改您的FQCN $logger 并使用这个use Psr\Log\LoggerInterface 而不是Monolog\Logger 另一件事,由于自动装配,您不需要在 service.yaml 中指定任何内容,除了这个(默认配置):

_defaults:
    autowire: true      # Automatically injects dependencies in your services.
    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
    public: false       # Allows optimizing the container by removing unused services; this also means
                        # fetching services directly from the container via $container->get() won't work.
                        # The best practice is to be explicit about your dependencies anyway.

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
    resource: '../src/*'
    exclude: '../src/{Entity,Migrations,Tests,Kernel.php}'

文档说:“核心捆绑包使用别名来允许自动装配服务。例如,MonologBu​​ndle 创建了一个 id 为 logger 的服务。但它也添加了一个别名:Psr\Log\LoggerInterface 指向记录器服务。这就是为什么使用 Psr\Log\LoggerInterface 类型提示的参数可以自动连接»所以在您的情况下, Psr\Log\LoggerInterface 是 Monolog https://symfony.com/doc/current/service_container/autowiring.html#using-aliases-to-enable-autowiring 的别名

【讨论】:

  • 我只使用 Symfony 的依赖注入组件,我的项目不是基于 Symfony 框架的。另外,我为什么要使用 LoggerInterface 而不是 Monolog?
  • 使用接口更容易,Symfony 中使用自动装配的许多组件应该与接口symfony.com/doc/current/service_container/…一起使用
  • 谢谢,我完全同意你所说的关于使用接口的说法,但是 autowire 也应该适用于像 Monlog 这样的具体类?
  • 非常好的问题,我应该花时间更深入地了解 DependencyInjection 组件。
【解决方案2】:

services.yaml 的内容似乎没有满。

你的服务文件应该是这样的

services:
  logger:
    class: Monolog\Logger
    arguments: ["application"]
    autowire: true
    public: true

  Monolog\Logger: '@logger'

  plugin_context:
    class: MyProject\PluginContext
    autowire: true
    public: true

【讨论】:

    猜你喜欢
    • 2020-03-08
    • 2014-12-03
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多