Symfony2 FOSUserBundle select locale on login and set it in session

As you may known since Symfony2.1 the locale is stored in the request.
Therfore in order to set/change the local, the most convenient way is to do it with the url.
See : Symfony documentation

I wanted somthing more hidden for the user.
I wanted the locale stored inside the user profile and set-up at the login time.
I am also using FOSUserBundle to handle the user management.

Here is how I did.

First : Make the locale "sticky" during the user's session

This is the easy part : everything is well described on the Symfony cookbook

Second Step : add a locale parameter to the FOSUserBundle

That is an easy step as well : if you followed the FosUserBundle documentation, you created your own user class : FOSUserBundle documentation

In my case, I used a Doctrine ORM Usser class.
So the only thing I had to do was to update the user.orm.yml :

#file : src/Acme/UserBundle/Resources/config/doctrine/user.orm.yml
    type:  entity
    table: fos_user
            type: integer
                strategy: AUTO
            type: string
            length: 2

And then run the usual following commands :

php app/console doctrine:generate:entities AcmeUserBundle

php app/console doctrine:schema:update --force

Third step : hook up on the logon event

It is pretty mutch like step 1 : create an event listener and add it inside the service configuration.

// file : src/Acme/UserBundle/EventListener/LoginListener.php
namespace Acme\UserBundle\EventListener;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
class LoginListener
     * @var string
    protected $locale;
     * Router
     * @var Router
    protected $router;
     * @var SecurityContext
    protected $securityContext;
     * @param SecurityContext $securityContext
     * @param Router $router The router
    public function __construct(SecurityContext $securityContext, Router $router)
        $this->securityContext = $securityContext;
        $this->router = $router;
    public function handle(AuthenticationEvent $event)
       $token = $event->getAuthenticationToken();
       $this->locale = $token->getUser()->getLocale();
    public function onKernelResponse(FilterResponseEvent $event)
        if (null !== $this->locale) {
            $request = $event->getRequest();
            $request->getSession()->set('_locale', $this->locale);

#file : src/Acme/UserBundle/Resources/config/services.yml
# ...
        class: Acme\UserBundle\EventListener\LoginListener
        arguments: [@security.context, @router]
            - { name: kernel.event_listener, event: security.authentication.success, method: handle }
            - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
# ...

Clear cache and your done.

php app/console cache:clear

Now if you have defined a locale for your user in the database, at the user's login, it will store it's locale inside the session.

postheadericon Commentaires