Symfony 2在控制器之间共享数据 [英] Symfony 2 sharing data between controllers

查看:118
本文介绍了Symfony 2在控制器之间共享数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始创建一个项目使用Symfony 2.我需要在所有控制器之间共享数据。

I have started to create a project using Symfony 2. I need to share data between all controllers.

我添加了一个基本控制器,扩展symfony \controller我的控制器扩展这个基本控制器

I have added a base controller which extends symfony\controller and each of my controllers extends this base controller

class BaseController extends Controller

class HomeController extends BaseController

这个基本控制器将用于类似分配全局树枝变量的事情(我知道我可以在config,但是一些变量将从其他配置文件和数据库获得)。

This base controller will be used for things like assigning global twig variables ( I know I can do this in the config but some of the variables will be gotten from other config files and database ).

所以我想我可以引用容器,因为Controller是容器感知的,但它不是在我使用函数(从构造函数)。

So I thought I could reference container since Controller is container aware, however it isn't at the point I am using the functions (from constructor).

public function __construct ()

我已经看到人们提到传递容器作为参数,提及服务,但我已经看了一下,不能弄清楚。我想要实现的是这样:

I have seen people mention passing the container in as a parameter and mention services but I have had a look and cannot figure it out. All I want to achieve is this:

public function __construct (Container $container) {
    $container->get('twig').addGlobal('foo');
}


推荐答案

这是一个常见的绊脚石到Symfony 2新手。

This is a common stumbling block to Symfony 2 newbies. The controller/container question has been asked hundreds of time before so you are not alone(hint).

为什么你的控制器构造函数代码不起作用?

Why doesn't your controller constructor code work?

首先查看vendor / symfony ... FrameworkBundle / Controller / Controller.php。嗯。没有建设者那里,那里的地方是容器从哪里来的?我们看到Controller扩展了ContainerAware。这似乎很有前途。我们来看看ContainerAware(命名空间有助于找到文件所在的位置),再次,没有构造函数。然而有一个setContainer方法,所以我们可以假设在构造函数被调用后容器被注入到控制器。在依赖注入的框架中非常常见。

Start by looking under vendor/symfony...FrameworkBundle/Controller/Controller.php. Hmm. No constructor there so where the heck is the container coming from? We see that Controller extends ContainerAware. That seems promising. We look at ContainerAware (the namespace helps to find where the file is) and once again, no constructor. There is however a setContainer method so we can assume that the container is injected into the controller after the constructor is called. Quite common in a dependency injection based framework.

现在我们知道为什么构造函数代码失败。容器尚未注入。愚蠢的设计权?不同框架的时间?不是真的。让我们面对它,不得不让所有的控制器扩展一个基本控制器只是为了获得一些twig变量设置不是真的最好的设计。

So now we know why the constructor code fails. The container has not yet been injected. Stupid design right? Time for a different framework? Not really. Let's face it, having to have all your controllers extend a base controller just to get some twig variables set is not really the best design.

Symfony在执行控制器动作之前执行代码的方法是创建一个控制器事件监听器。它将看起来像这样:

The Symfony way to execute code before the controller action is executed is to make a controller event listener. It will look something like this:

namespace Cerad\Bundle\CoreBundle\EventListener;

use Symfony\Component\DependencyInjection\ContainerAware;

use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ModelEventListener extends ContainerAware implements EventSubscriberInterface
{   
    public static function getSubscribedEvents()
    {
        return array(KernelEvents::CONTROLLER => array(
            array('doTwig', 0), // 0 is just the priority
        ));
    }
    public function doTwig(FilterControllerEvent $event)
    {
        // Ignore sub requests
        if (HttpKernel::MASTER_REQUEST != $event->getRequestType()) return;

        $this->container->get('twig')->addGlobal('foo');
    }
}
// This goes in services.yml

parameters:
    cerad_core__model_event_listener__class: 
        Cerad\Bundle\CoreBundle\EventListener\ModelEventListener

services:
    cerad_core__model_event_listener:
        class:  '%cerad_core__model_event_listener__class%'
        calls:
            - [setContainer, ['@service_container']]
        tags:
            - { name: kernel.event_subscriber }

所以现在我们有所需的功能,而不需要一个基本控制器类。

So now we have the desired functionality without the need for a base controller class.

请注意,可以通过事件访问控制器。由于控制器已创建,但action方法尚未调用,您可以调用控制器方法或将数据直接注入控制器。这很少需要。在大多数情况下,您可以向请求对象添加其他信息,然后将其注入到控制器的操作方法中。

Notice also that the controller can be accessed through the event. Since the controller has been created but the action method not yet called, you could call controller methods or inject data directly into the controller. This is seldom needed. In most cases, you would add additional information to the request object which then gets injected into the controller's action method.

这是一个不错的设计,

It's really a nice design once you get comfortable with listeners and services.

这篇关于Symfony 2在控制器之间共享数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆