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.