我正在将一个Symfony 2.8
项目迁移到Symfony 3.4
。该项目使用Doctrine 2.6.3
和FOSUserBundle 2.1.2
。
在创建并确认新用户帐户后,项目会监听FOSUserEvents::REGISTRATION_CONFIRMED
进行一些额外的设置工作。
public static function getSubscribedEvents() {
return array(
FOSUserEvents::REGISTRATION_CONFIRMED => 'onRegistrationConfirmed',
);
}
public function onRegistrationConfirmed(FilterUserResponseEvent $event) {
$this->logger->info("onRegistrationConfirmed");
$user = $event->getUser();
// Do some additional setup. While the confirmed user in known here,
// other setup classes / methods get the current user from tokenStorage
ThirdPartySetupCode();
}
// Some 3rd party class I cannot change
public function ThirdPartySetupCode() {
$token = $this->tokenStorage->getToken();
if (!$token) {
$user = $token->getUser();
...
}
}
在Symfony 2.8
和Symfony 3.4
中处理事件的方式看来似乎有所不同:
虽然以上代码在Symfony 2.8
中运行没有问题,但在Symfony 3.4
中却失败了,因为$token->getUser()
不会返回有效的用户对象,而只是返回字符串anon.
(匿名)用户。
这是在Symfony 2.8中处理事件的方式:
dispatch: kernel.request
dispatch: security.authentication.success
dispatch: kernel.controller
dispatch: fos_user.registration.confirm
dispatch: fos_user.registration.confirmed
dispatch: fos_user.security.implicit_login
onRegistrationConfirmed
令人惊讶的是,onRegistrationConfirmed
日志输出直接出现在 fos_user.registration.confirmed
之后。事件触发后,处理程序是否应立即执行?
相反,首先分派(和处理?)fos_user.security.implicit_login
事件,然后才分派onRegistrationConfirmed
处理程序?
这是为什么?但是,尽管我不了解这种行为,但它会导致预期的结果:由于处理程序(以及第三方代码)在登录完成后运行,因此令牌返回正确的用户。
这是在Symfony 3.4中处理事件的方式:
dispatch: kernel.request
dispatch: security.authentication.success
dispatch: kernel.controller
dispatch: kernel.controller_arguments
dispatch: fos_user.registration.confirm
dispatch: fos_user.registration.confirmed
onRegistrationConfirmed
dispatch: fos_user.security.implicit_login
在onRegistrationConfirmed
事件之后直接执行fos_user.registration.confirmed
处理程序。
虽然我理解此行为会导致错误的结果:处理程序(以及第3方代码)在登录之前完全运行BEVOR,因此令牌不会返回有效用户。
如何解决此问题?由于我无法更改第三方代码,因此必须以某种方式延迟对fos_user.registration.confirmed
的处理,以便首先完成登录。能做到吗?
事件分发和处理Symfony 2.8
和Symfony 3.4
之间的预期更改是否存在差异?我没有找到任何相关信息。