FOSUserBundle:使用EventListener注册后重定向用户

use*_*964 12 redirect event-listener symfony fosuserbundle

我想在注册之后将用户重定向到另一个表单,然后才能访问我网站上的任何内容(例如https://github.com/FriendsOfSymfony/FOSUserBundle/issues/387).

所以我在doc中创建了一个eventListener:

<?php
namespace rs\UserBundle\EventListener;

use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\UserEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

/**
 * Listener responsible to change the redirection at the end of the password resetting
 */
class RegistrationConfirmedListener implements EventSubscriberInterface
{
    private $router;

    public function __construct(UrlGeneratorInterface $router)
    {
        $this->router = $router;
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
                FOSUserEvents::REGISTRATION_CONFIRMED => 'onRegistrationConfirmed'
        );
    }

    public function onRegistrationConfirmed()
    {
        $url = $this->router->generate('rsWelcomeBundle_check_full_register');
        $response = new RedirectResponse($url);
        return $response;
    }
}
Run Code Online (Sandbox Code Playgroud)

Services.yml:

services:
    rs_user.registration_completed:
        class: rs\UserBundle\EventListener\RegistrationConfirmedListener
        arguments: [@router]
        tags:
            - { name: kernel.event_subscriber }
Run Code Online (Sandbox Code Playgroud)

但它不起作用,用户注册,他点击他邮箱中的确认链接,他没有被重定向到我想要的页面上,他被记录了,我只是有消息谁说帐户已经确认.

为什么它不会将我重定向到路线:rsWelcomeBundle_check_full_register就像我想要的那样?

谢谢

che*_*fly 27

要完成你想要的,你应该使用FOSUserEvents::REGISTRATION_CONFIRM而不是FOSUserEvents::REGISTRATION_CONFIRMED.

然后你必须重写你的类,RegistrationConfirmedListener如:

class RegistrationConfirmListener implements EventSubscriberInterface
{
    private $router;

    public function __construct(UrlGeneratorInterface $router)
    {
        $this->router = $router;
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
                FOSUserEvents::REGISTRATION_CONFIRM => 'onRegistrationConfirm'
        );
    }

    public function onRegistrationConfirm(GetResponseUserEvent $event)
    {
        $url = $this->router->generate('rsWelcomeBundle_check_full_register');

        $event->setResponse(new RedirectResponse($url));
    }
}
Run Code Online (Sandbox Code Playgroud)

你的service.yml:

services:
    rs_user.registration_complet:
        class: rs\UserBundle\EventListener\RegistrationConfirmListener
        arguments: [@router]
        tags:
            - { name: kernel.event_subscriber }
Run Code Online (Sandbox Code Playgroud)

REGISTRATION_CONFIRM接收一个FOS\UserBundle\Event\GetResponseUserEvent实例,你可以在这里看到:https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/FOSUserEvents.php

它允许您修改将要发送的响应:https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Event/GetResponseUserEvent.php

  • **对于未来的读者,如果您使用HWIOAuthBundle,请注意:**"HWIOAuthBundle不使用FOSUserBundle注册控制器,因此它永远不会触发这些事件." [http://stackoverflow.com/questions/18493324/hwioauthbundle-fosuserbundle-events-not-firing](http://stackoverflow.com/questions/18493324/hwioauthbundle-fosuserbundle-events-not-firing);) (9认同)
  • 对我来说(使用FOSUserBundle和HWIOAuthBundle),只有`REGISTRATION_SUCCESS`能像预期的那样工作. (3认同)

Blo*_*kas 6

"friendsofsymfony/user-bundle": "2.0.x-dev",
Run Code Online (Sandbox Code Playgroud)

不确定为什么接受的答案适合您,因为REGISTRATION_CONFIRM在确认令牌后发生.

如果你想执行一个动作,在FOS registerAction之后用一些额外的形式重定向到另一个页面,我建议采用以下方法.

这是FOS提交的表单生效后在registerAction上执行的代码:

FOS\UserBundle \控制器\这个RegistrationController

        if ($form->isValid()) {
            $event = new FormEvent($form, $request);
            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

            $userManager->updateUser($user);

            if (null === $response = $event->getResponse()) {
                $url = $this->generateUrl('fos_user_registration_confirmed');
                $response = new RedirectResponse($url);
            }

            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

            return $response;
        }
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,第一个可能的返回发生在FOSUserEvents :: REGISTRATION_SUCCESS事件之后,如果响应为null,在我的情况下没有,因为我已经配置了邮件程序来发送确认令牌而FOS正在使用侦听此FOSUserEvents的侦听器:: REGISTRATION_SUCCESS事件,并在发送电子邮件后设置重定向响应.

FOS\UserBundle \事件监听\ EmailConfirmationListener

/**
 * @return array
 */
public static function getSubscribedEvents()
{
    return array(
        FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
    );
}

/**
 * @param FormEvent $event
 */
public function onRegistrationSuccess(FormEvent $event)
{
    /** @var $user \FOS\UserBundle\Model\UserInterface */
    $user = $event->getForm()->getData();

    $user->setEnabled(false);
    if (null === $user->getConfirmationToken()) {
        $user->setConfirmationToken($this->tokenGenerator->generateToken());
    }

    $this->mailer->sendConfirmationEmailMessage($user);

    $this->session->set('fos_user_send_confirmation_email/email', $user->getEmail());

    $url = $this->router->generate('fos_user_registration_check_email');
    $event->setResponse(new RedirectResponse($url));
}
Run Code Online (Sandbox Code Playgroud)

好的我明白!那么如何重定向到另一个页面?

我建议覆盖checkEmailAction,因为很可能你不想覆盖发送电子邮件的监听器,因为这是你工作流程的一部分.

只是:

TB\UserBundle \控制器\这个RegistrationController

/**
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function checkEmailAction()
{
    /** @var UserManager $userManager */
    $userManager = $this->get('fos_user.user_manager');
    /** @var string $email */
    $email = $this->get('session')->get('fos_user_send_confirmation_email/email');

    $user = $userManager->findUserByEmail($email);

    return $this->redirect($this->generateUrl('wall', ['username' => $user->getUsername()]));
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我决定将用户重定向到他的新配置文件而不是呈现FOS的check_email模板.

Docs如何覆盖控制器:https://symfony.com/doc/master/bundles/FOSUserBundle/overriding_controllers.html(基本上为您的捆绑包定义一个父级,并在目录中创建一个与FOS同名的文件.)