Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor in Symfony2 Controller

How can I define a constructor in Symfony2 controller. I want to get the the logged in user data available in all the methods of my controller, Currently I do something like this in every action of my controller to get the logged in user.

$em = $this->getDoctrine()->getEntityManager("pp_userdata");
$user = $this->get("security.context")->getToken()->getUser();

I want to do it once in a constructor and make this logged in user available on all my actions

like image 732
Zoha Ali Khan Avatar asked Jun 24 '12 16:06

Zoha Ali Khan


3 Answers

For a general solution for executing code before every controller action you can attach an event listener to the kernel.controller event like so:

<service id="your_app.listener.before_controller" class="App\CoreBundle\EventListener\BeforeControllerListener" scope="request">
    <tag name="kernel.event_listener" event="kernel.controller" method="onKernelController"/>
    <argument type="service" id="security.context"/>
</service>

Then in your BeforeControllerListener you will check the controller to see if it implements an interface, if it does, you will call a method from the interface and pass in the security context.

<?php

namespace App\CoreBundle\EventListener;

use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Security\Core\SecurityContextInterface;
use App\CoreBundle\Model\InitializableControllerInterface;

/**
 * @author Matt Drollette <[email protected]>
 */
class BeforeControllerListener
{

    protected $security_context;

    public function __construct(SecurityContextInterface $security_context)
    {
        $this->security_context = $security_context;
    }

    public function onKernelController(FilterControllerEvent $event)
    {
        $controller = $event->getController();

        if (!is_array($controller)) {
            // not a object but a different kind of callable. Do nothing
            return;
        }

        $controllerObject = $controller[0];

        // skip initializing for exceptions
        if ($controllerObject instanceof ExceptionController) {
            return;
        }

        if ($controllerObject instanceof InitializableControllerInterface) {
            // this method is the one that is part of the interface.
            $controllerObject->initialize($event->getRequest(), $this->security_context);
        }
    }
}

Then, any controllers that you want to have the user always available you will just implement that interface and set the user like so:

use App\CoreBundle\Model\InitializableControllerInterface;

class DefaultController implements InitializableControllerInterface
{
    /**
     * Current user.
     *
     * @var User
     */
    private $user;

    /**
     * {@inheritdoc}
     */
    public function initialize(Request $request, SecurityContextInterface $security_context)
    {
        $this->user = $security_context->getToken()->getUser();
    }
// ....
}

The interface is nothing more than

namespace App\CoreBundle\Model;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContextInterface;

interface InitializableControllerInterface
{
    public function initialize(Request $request, SecurityContextInterface $security_context);
}
like image 106
MDrollette Avatar answered Nov 14 '22 04:11

MDrollette


I'm runnig a bit late, but in a controller you can just access the user:

$this->getUser();

Should be working since 2.1

like image 41
Moritz Avatar answered Nov 14 '22 06:11

Moritz


My approach to this was:

  1. Make an empty Interface InitializableControllerInterface
  2. Make event Listener for
namespace ACMEBundle\Event;

use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

class ControllerConstructor
{
    public function onKernelController(FilterControllerEvent $event)
    {
        $controller = $event->getController();
        if (!is_array($controller)) {
            // not a object but a different kind of callable. Do nothing
            return;
        }

        $controllerObject = $controller[0];
        if ($controllerObject instanceof InitializableControllerInterface) {
            $controllerObject->__init($event->getRequest());
        }
    }
}
  1. In your controller add:
class ProfileController extends Controller implements
        InitializableControllerInterface
{
public function __init()
    {
$this->user = $security_context->getToken()->getUser();
}

And you will be able to get the $this->user in each action.

Regards

like image 41
Max Małecki Avatar answered Nov 14 '22 04:11

Max Małecki