Symfony 2 sharing data between controllers

六月ゝ 毕业季﹏ 提交于 2020-01-02 13:27:14

问题


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

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

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 ).

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');
}

回答1:


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?

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.

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.

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.

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.




回答2:


Please read carefully that question - Symfony2 passing data between bundles & controllers, try to use code included in it.

You can use service to solve your problem, for example.




回答3:


If you look at the Controller class you'll se the following:

class Controller extends ContainerAware

This means you can retrieve twig from the container as simple as this:

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

But I would recommend you to use custom twig extension in your case.



来源:https://stackoverflow.com/questions/21875810/symfony-2-sharing-data-between-controllers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!