【问题标题】:Symfony 4 Dependency Injection: Inject into object while creating it in codeSymfony 4 依赖注入:在代码中创建对象时注入对象
【发布时间】:2019-04-19 20:18:12
【问题描述】:

我正在为我的后端创建一个 NavigationBuilder 类。有了它,我应该可以添加导航项,然后获取 html(类似于 Symfony 的 FormBuilder)。它用于 Twig 扩展函数。

我有一个导航项目(例如导航链接、分隔线、标题等)的 interfaceabstract 类,我正在为这些特定项目创建子类。

对于其中一些导航项(链接),我需要 Symfony RouterRequestStack,并且我想将它注入到抽象类中,因此我不必将它作为参数传递给每个我需要它的子类。

我尝试使用 setter 方法注入它的方法,因为我认为 Symfony 会在我创建新对象时自动执行此操作,但显然情况并非如此。

NavigationItem 类:

namespace App\...\Navigation;

use App\...\NavigationItemInterface;
use Symfony\...\UrlGeneratorInterface;
use Symfony\...\Request;

abstract class NavigationItem implements NavigationItemInterface {

  private $router;
  private $request;

  final public function setRouter(UrlGeneratorInterface $router): self {
    $this->router = $router;
    return $this;
  }

  final public function setRequest(Request $request): self {
    $this->request = $request;
    return $this;
  }

  final public function matchesCurrentRoute(String $route): Bool {
    return $this->getRequest()->get('_route') == $route;
  }

  /** ... **/
}

我的service.yaml 文件:

App\...\NavigationItem:
        class: App\...\NavigationItem
        calls:
            - method: setRequest
              arguments:
                - '@request_stack'
            - method: setRouter
              arguments:
                - '@router'

我想它是这样工作的:

$builder = new NavigationBuilder();
$builder
  ->addItem( new HeaderItem('A Heading') ) // No need for injection
  ->addItem( new LinkItem('Title', 'route') ) // NEED for injection
->build(); // Returns html

我收到此错误代码:

在渲染模板期间抛出异常(“注意:未定义属性:App...\DashboardItem::$router”)。

【问题讨论】:

  • 我认为您需要访问内核 di 容器并从那里获取路由器实例。 Symfony 仅支持控制器和服务而不是通用类的自动装配功能。这是我的理解
  • 我个人建议你使用 KnpMenuBundle symfony.com/doc/master/bundles/KnpMenuBundle/index.html 或深入研究它的源代码,看看他们是如何处理它的 github.com/KnpLabs/KnpMenuBundle
  • php new 操作符对 di 容器一无所知。所以你的基本希望是,嗯,没有希望。您的导航构建器应该是一项服务并在需要的地方注入。然后构建器本身可以负责创建菜单项等内容并根据需要注入请求。
  • @Cerad 嘿,谢谢你的回答!是的,这是我的新方法。创建我的 NavigationBuilder 类并将其作为服务注入到我的 Twig Extension 类中。

标签: php symfony dependency-injection


【解决方案1】:

如果您将属性声明为private,则只有类本身,但没有子类可以使用它(即直接使用)。声明它protected(谈论抽象类中的router 属性)参见:https://www.php.net/manual/en/language.oop5.visibility.php

显然这不是唯一的问题,我想您将依赖注入与自动装配混淆了。依赖注入仅意味着对象不会创建它自己的依赖项,而是通过参数(在构造函数、setter 或特定调用中)来自外部/调用者。

自动连接在 symfony 中通过从容器中获取一个对象来工作(然而,by default you always get the same object。但有一些方法可以达到define a factory or the option to always retrieve a new object,可能,不太确定)。

【讨论】:

  • 对,我确实忘记了可见性,但我认为它不能解决我最初的问题。 '在 null 上调用成员函数。' 当我尝试访问项目的 $router 属性时,它会这样说。
  • @Fabian 我认为您将依赖注入与自动装配/自动配置混淆了。如果我站在你的立场上,我会把抽象类变成一个工厂,让它产生 headeritems 和 linkitems(或者多个工厂,就此而言)。当对象/调用由框架完成时,自动装配/自动配置仅适用于参数。
猜你喜欢
  • 1970-01-01
  • 2013-06-14
  • 2015-01-22
  • 2019-01-05
  • 2013-03-03
  • 2011-12-31
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多