Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 - How to use __construct() in a Controller and access Securty.Context?

Tags:

php

symfony

I am having some trouble with Symfony2. Namely in how to use the __construct() function. the Official Documentation is shockingly bad!

I want to be able to use the following:

public function __construct()
{
    parent::__construct();
    $user = $this->get('security.context')->getToken()->getUser();
}

How ever I get the following error:

Fatal error: Cannot call constructor in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 11

Line 11 is "parent::__construct();"

I removed it and got the following, new error

Fatal error: Call to a member function get() on a non-object in /Sites/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 242

I think I might need to set up the ContainerInterface DIC, but I have no idea how to do this (I tried and failed, miserably)

Any ideas folks?

Update - Tried changing to extend ContainerAware and got this error:

Fatal error: Class DEMO\DemoBundle\Controller\Frontend\HomeController cannot extend from interface Symfony\Component\DependencyInjection\ContainerAwareInterface in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 43

Using the following code in the controller:

<?php

namespace DEMO\DemoBundle\Controller\Frontend;

use Symfony\Component\DependencyInjection\ContainerAware;

class HomeController extends ContainerAwareInterface
{
     protected $container;

     public function setContainer(ContainerInterface $container = null)
     {
         $this->container = $container;
     }
like image 426
Mr Pablo Avatar asked Mar 16 '12 11:03

Mr Pablo


2 Answers

I'm assuming you are extending the default Symfony controller? If so, a look at the code will reveal the answer:

namespace Symfony\Bundle\FrameworkBundle\Controller;

use Symfony\Component\DependencyInjection\ContainerAware;

class Controller extends ContainerAware
{

Notice that there is no Controller::__construct defined so using parent::__construct will not get you anywhere. If we look at ContainerAware:

namespace Symfony\Component\DependencyInjection;

class ContainerAware implements ContainerAwareInterface
{
    protected $container;
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}

Again, no constructor and the container is not available until setContainer is called. So override setContainer and put your logic there. Or else just make a stand alone controller that does not extend the base controller class and inject your dependencies directly into the constructor.

Update Aug 2017

Still getting a few hits on this. If you really want to execute something before each controller then use a kernel controller listener. If all you need is the user then of course use getUser(). And please don't override setContainer(). In some cases it would work but it would just convolute your code.

like image 185
Cerad Avatar answered Sep 19 '22 09:09

Cerad


I also frequently want an instance of the current User in most of my controllers. I find it is easiest to just do something like this:

class SomeController extends Controller
{
    protected $user;

    public function getUser()
    {
        if ($this->user === null) {
            $this->user = $this->get('security.context')->getToken()->getUser();
        }
        return $this->user;
    }
}

However, this is an overly simplistic example case. If you want to do more work before a Controller action is started, I suggest you define your Controller as a Service.

Also take a look at this article: Moving Away from the Base Controller

like image 37
leek Avatar answered Sep 20 '22 09:09

leek