2014-02-19 69 views
2

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

我已经添加了延伸的symfony \控制器的基础控制器和我的每个控制器扩展了该基地控制器

class BaseController extends Controller 

class HomeController extends BaseController 

这个基地控制器将被用于诸如分配全局树枝变量(我知道我可以做这在配置中,但一些变量将从其他配置文件和数据库中获得)。

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

public function __construct() 

我已经看到有人提到通过容器作为参数和提及服务,但我看了一下,不知道它。所有我想要实现的是:

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

回答

6

这是Symfony 2新手常见的绊脚石。控制器/容器问题在数百次之前已经被问过,所以你并不孤单(提示)。

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

从供应商/ symfony下寻找... FrameworkBundle/Controller/Controller.php。嗯。那里没有构造器,那么容器是从哪里来的?我们看到Controller扩展了ContainerAware。这似乎很有希望。我们看看ContainerAware(命名空间有助于查找文件的位置),并且再次没有构造函数。然而,有一个setContainer方法,所以我们可以假定在构造函数被调用后,容器被注入到控制器中。在基于依赖注入的框架中很常见。

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

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

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 } 

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

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

一旦您对听众和服务感到满意,这真的是一个不错的设计。

0

如果你看一下控制器类,你会SE以下:

class Controller extends ContainerAware 

这意味着你可以从容器这么简单检索枝:

$twig = $this->get('twig'); 

但我会建议你在你的情况下使用custom twig extension

相关问题