我正在尝试添加一个Symfony2登录事件监听器,目标是在每个请求上记录用户时设置数据库存储的语言环境,并回退到默认的没有用户登录的语言环境。 我使用FOSUserBundle,我试图让security.interactive_login事件起作用。我在互联网上找到了很多像这样的代码:http://dev.dbl-a.com/symfony-2-0/how-to-add-a-symfony2-login-event-listener/
我有自己的FOSUserBundle子包和services.yml中的这个实现:
my_user.security.interactive_login_listener:
class: My\UserBundle\EventListener\UserListener
arguments: [@security.context, @doctrine]
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: setLocaleForAuthenticatedUser }
my_user.security.kernel_request_listener:
class: My\UserBundle\EventListener\UserListener
arguments: [@security.context, @doctrine]
tags:
- { name: kernel.event_listener, event: kernel.request, method: setLocaleForUnauthenticatedUser }
问题是,即使在记录时,也永远不会触发security.interactive_login事件。相反,我的setLocaleForUnauthenticatedUser总是被触发。 我找到的每个代码示例似乎都很流畅,我的应用程序出了什么问题?
答案 0 :(得分:1)
也计算出来,做了或多或少同样的工作: 确实没有问题,但登录后会有某种重定向,因此探查器永远不会显示触发交互式登录监听器的实际请求。
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent,
Symfony\Component\Security\Http\Event\FilterControllerEvent,
Symfony\Component\HttpKernel\Event\GetResponseEvent,
Symfony\Component\HttpKernel\HttpKernelInterface;
use FOS\UserBundle\Entity\User as BaseUser;
class LocaleListener {
protected $container;
protected $availableLocales;
public function __construct(\Symfony\Component\DependencyInjection\Container $container, $availableLocales) {
$this->container = $container;
$this->availableLocales = $availableLocales;
}
public function onKernelRequest(GetResponseEvent $event) {
$request = $event->getRequest();
$locale = $request->getPreferredLanguage($this->availableLocales);
$session = $request->getSession();
$token = $this->container->get('security.context')->getToken();
if( is_object( $token ) ) {
$user = $token->getUser();
if ($user instanceof BaseUser) {
$locale = $user->getLocale();
}
}
$session = $this->container->get('session');
$session->set('_locale', $locale);
$request->setLocale($locale);
}
}
在services.yml:
user.locales.kernel_request_listener:
class: Acme\UserBundle\EventListener\LocaleListener
arguments: [ @service_container, [ 'en', 'fr', 'ru' ] ]
tags: [{ name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: -255 }]
答案 1 :(得分:0)
这里的问题相同。但问题不在于没有触发事件。问题是重定向后,请求区域设置丢失。在此链接的帮助下:
Changing locale with symfony 2.1
(并基于this)
我想出了如何解决它。在UserListener中:
class UserListener
{
private $session;
public function setSession($session) {
$this->session = $session;
}
public function setLocaleForUnauthenticatedUser(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$request = $event->getRequest();
if ('undefined' == $request->getLocale()) {
if($locale = $request->getSession()->get('_locale')) {
$request->setLocale($locale);
} else {
$request->setLocale($request->getPreferredLanguage());
}
}
}
public function setLocaleForAuthenticatedUser(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
if ($locale = $user->getLocale()) {
// $event->getRequest()->setLocale($user->getLocale());
$this->session->set('_locale', $locale);
}
}
}
在services.yml中,您应该声明:
your_listener_name:
class: ...\UserBundle\EventListener\UserListener
calls:
- [ setSession, ['@session'] ]
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: setLocaleForAuthenticatedUser }
希望这有帮助。