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
Acme\UserBundle\Entity\User:
    type:  entity
    table: fos_user
    id:
        id:
            type: integer
            generator:
                strategy: AUTO
    fields:
        locale:
            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.

 
<?php
// 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
services:
# ...
    acme.user.login:
        class: Acme\UserBundle\EventListener\LoginListener
        arguments: [@security.context, @router]
        tags:
            - { 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