2014-02-19 70 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

相關問題