SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Enthusiast doddsey_65's Avatar
    Join Date
    Sep 2010
    Location
    North East UK
    Posts
    77
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Sharing data between Symfony 2 Controllers

    Hi, 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

    PHP Code:
    class BaseController extends Controller 
    PHP Code:
    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).

    PHP Code:
    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:

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

    Test and help out with a new
    100% open source forum package: A Simple Forum
    Check the A Simple forum Github Page
    Visit my Github profile to see what I work on.

  2. #2
    SitePoint Guru
    Join Date
    Nov 2003
    Location
    Huntsville AL
    Posts
    689
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    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.

    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:

    PHP Code:
    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:
                - { 
    namekernel.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.

  3. #3
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,266
    Mentioned
    18 Post(s)
    Tagged
    0 Thread(s)
    +1 for a great answer.

    I'll also leave this documentation page here.

    http://symfony.com/doc/current/cookb...variables.html

    Adding globals into our templates is common enough that Symfony made it even easier.
    "First make it work. Then make it better."

  4. #4
    SitePoint Enthusiast doddsey_65's Avatar
    Join Date
    Sep 2010
    Location
    North East UK
    Posts
    77
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Awesome post @ahundiak, thanks. I have since decided to stick to Silex since I am more comfortable with it and it seems it would take a while to migrate the whole project over. I would like to start using Symfony for it but not sure it is the best option at this stage. I will, however, implement your code in a test project to learn more about how Symfony works.
    Test and help out with a new
    100% open source forum package: A Simple Forum
    Check the A Simple forum Github Page
    Visit my Github profile to see what I work on.

  5. #5
    SitePoint Guru
    Join Date
    Nov 2003
    Location
    Huntsville AL
    Posts
    689
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Consider accepting my answer on the site that just over flows with questions. Cerad

  6. #6
    SitePoint Enthusiast doddsey_65's Avatar
    Join Date
    Sep 2010
    Location
    North East UK
    Posts
    77
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Didn't see that answer. Accepted.
    Test and help out with a new
    100% open source forum package: A Simple Forum
    Check the A Simple forum Github Page
    Visit my Github profile to see what I work on.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •