Php 在控制器构造函数Symfony上加载容器服务

Php 在控制器构造函数Symfony上加载容器服务,php,symfony,Php,Symfony,有没有办法在控制器构造函数中加载容器服务,比如 class PostController extends Controller { protected $breadcrumb; public function __construct() { //initializing breadcrumb $breadcrumbs = $this->get("white_october_breadcrumbs"); $bread

有没有办法在控制器构造函数中加载容器服务,比如

class PostController extends Controller
{

    protected $breadcrumb;

    public function __construct()
    {
        //initializing breadcrumb
        $breadcrumbs = $this->get("white_october_breadcrumbs");
        $breadcrumbs->addRouteItem("Dashboard", "adminPage");
        $breadcrumbs->addRouteItem("Post", "postPage");
        $this->breadcrumb = $breadcrumbs;
    }
//..
}

您正在扩展
Symfony\Bundle\FrameworkBundle\Controller\Controller
类,该类通过setter注入(方法
setContainer
)而不是通过构造函数参数注入
container

当您在
\u构造()
中时,您还没有可用的
$container
。所以,您的解决方案是重写
setContainer
方法(在构造控制器之后由服务容器调用),并将您的逻辑放在那里(而不是
\u construct()

另一个解决方案需要做更多的工作,就是将其设置为
容器
作为构造函数参数

是的,这可以通过。然而,注入容器被认为是一个糟糕的例子。如果您想获得服务
白色\u十月\u面包屑
,您可以将其插入控制器服务定义中;如果您使用yaml:

service:
    class: app.controller.my_controller
    arguments:
        - "@white_october_breadcrumbs"
public function\u构造(Breadcrumbs$Breadcrumbs)
{
$this->breadcrumbs=$breadcrumbs;
}
这是一个更好的解决方案,因为您不希望应用程序尽可能依赖于容器

考虑到您希望在多个页面上实现这一点,另一个解决方案是在操作上使用事件侦听器甚至自定义注释来动态添加面包屑。但这不建议初学者使用

在控制器构造函数Symfony上加载容器服务

不要。您的服务生命周期是什么?如果调用了控制器的操作,是否要初始化一些面包屑?那次请求呢?控制器的创建顺序是什么

1。任一中央配置:

  • 创建一个配置映射(例如在yml中),控制器类名作为键,面包屑作为值(例如路由数组)
  • 创建一个
    BreadcrumbBuilder
    服务,注入配置
  • 为您的视图创建一个
    BreadcrumbProvider
    独立服务和细枝扩展
  • 创建并注册一个
    BreadcrumbRequestListener
    监听器,注入
    BreadcrumbBuilder
    ,`BreadcrumbProvider
  • 根据
    getController()
    -callable创建面包屑(示例A)
  • 直接在twig中访问面包屑
  • 样本A:

    $controller = $event->getController();
    if(\is_array($controller)) {
      $clazz = \get_class($controller[0]);
      $breadcrumbs = $this->breadcrumbBuilder->build($clazz);
      $this->breadcrumbProvider->setBreadcrumbs($breadcrumbs);
    }
    
    2。或者打开关闭的控制器,这样您就不需要更改中心配置,只需添加控制器:

  • 让每个提供面包屑的控制器成为
    BreadcrumbProviderInterface
    实现
    getBreadcrumb()
    返回创建面包屑所需的一些数据
  • 还要创建一个
    BreadcrumbRequestListener
    ,检查该接口并存储可通过twig访问的引用(示例B)
  • 样本B:

    $controller = $event->getController();
    if(\is_array($controller) && $controller[0] instanceof BreadcrumbProviderInterface) {
      $this->breadcrumbs->setCurrentProvider($controller[0]);
    }
    
    3。其他想法:

    • 通过遍历
      request\u堆栈
      请求面包屑,并在
      $request->attributes->get(“u controller”)上执行控制器和操作。您可以只使用主请求,也可以遍历来自所有控制器的所有面包屑
    • 基本控制器类

      • 我也有类似的案例。下面是我的场景: 我有一个第三方bundle类,在
        vendor/my vendor/my third party bundle/Resources/config/services.xml
        中声明为服务,我想将其注入我的
        src/AppBundle/Controller/MyController
        。当我在上面控制器的某个操作方法中从容器中获取第三方bundle类时,名称空间设置正确,一切正常。例如:
        
        类MyController扩展控制器
        {
        公共职能行动()
        {
        // ...
        $myThirdPartyBundleService=$this->container
        ->get('my_third_party_bundle_service.class');
        // ...
        }
        }
        
        我尝试的是按照官方(Symfony docs)[将控制器声明为服务,因为我在控制器中多次使用该服务。
        似乎在
        MyThirdPartyBundle\DependencyInjection\MyThirdPartyBundleExtension::load()
        中我有了服务构建。我还尝试将
        die('my-third-party-bundle');
        放在load()方法和
        MyAppBundle\Controller\MyControl::\uu construct()
        中我尝试了
        die('Controller')
        只是想看看哪一个是先加载的。正如我所料,首先返回的结果是来自第三方捆绑包的结果。我还尝试了
        die('my_app_bundle');
        MyAppBundle\DependencyInjection\MyAppBundleExtension::load()中
        。正如我所尝试的,结果取决于捆绑包在AppKernel中声明的顺序。因此,我将MyThirdPartyBundle更改为在MyAppBundle之前加载。我仍然没有得到所需的结果,而是得到了
        NULL
        。似乎此时我的第三方捆绑包的类还没有生成。我没有太多时间检查为什么会发生这种情况,但我怀疑原因是容器的配置构建。因此,我可以做的最简单、最快速的事情是覆盖Symfony\Component\DependencyInjection\ContainerInterface::setContainer()```在MyAppBundle的控制器中。这不是解决问题的最优雅的方法,但它是有效的。我认为正确的方法是将控制器声明为服务,但在我的情况下它似乎不起作用。

        将每个控制器类定义为服务对我来说没有意义,我想为多个页面添加面包屑,以便您可以详细介绍第二种方法或另一种简单的方法。我建议将每个控制器作为一种服务,因为从长远来看,这将对您有所帮助。如果您想在特定时刻触发事件,可以使用kernel.request和kernel.controller事件。这将解决问题,但我认为这不是最好的方法和sa
        $controller = $event->getController();
        if(\is_array($controller) && $controller[0] instanceof BreadcrumbProviderInterface) {
          $this->breadcrumbs->setCurrentProvider($controller[0]);
        }