FOSUserBundle: перенаправить пользователя после регистрации в EventListener
Я хочу перенаправить пользователя в другую форму сразу после регистрации, прежде чем он сможет получить доступ к чему-либо на моем веб-сайте (например, https://github.com/FriendsOfSymfony/FOSUserBundle/issues/387).
Итак, я создаю 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;
}
}
Services.yml:
services:
rs_user.registration_completed:
class: rs\UserBundle\EventListener\RegistrationConfirmedListener
arguments: [@router]
tags:
- { name: kernel.event_subscriber }
Но он не работает, пользователь регистрируется, он нажимает ссылку подтверждения в своем почтовом ящике, он не перенаправляется на страницу, которую я хочу, он зарегистрирован, и у меня есть сообщение, в котором говорится, что учетная запись подтверждена.
Почему это не перенаправляет меня на маршрут: rsWelcomeBundle_check_full_register, как я хочу?
Спасибо
Ответы
Ответ 1
Чтобы выполнить то, что вы хотите, вы должны использовать 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));
}
}
И ваш service.yml
:
services:
rs_user.registration_complet:
class: rs\UserBundle\EventListener\RegistrationConfirmListener
arguments: [@router]
tags:
- { name: kernel.event_subscriber }
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
Ответ 2
"friendsofsymfony/user-bundle": "2.0.x-dev",
Не уверен, почему принятый ответ работает для вас, поскольку REGISTRATION_CONFIRM происходит после подтверждения токена.
Если вы хотите выполнить действие, перенаправьте на другую страницу с некоторой дополнительной формой после действия FOS registerAction. Я бы предложил следующий путь.
Это код, который выполняется на registerAction после того, как отправленная форма действительна для FOS:
FOS\UserBundle\Controller\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;
}
Как вы можете видеть, первый возможный возврат происходит после события FOSUserEvents :: REGISTRATION_SUCCESS в случае, если ответ нулевой, что в моем случае не так, как я настроил почтовую программу для отправки токена подтверждения, а FOS использует прослушиватель, который слушает этот FOSUserEvents :: REGISTRATION_SUCCESS событие и после отправки электронного письма устанавливает ответ перенаправления.
FOS\UserBundle\EventListener\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));
}
Хорошо, я понял! Так как мне перенаправить на другую страницу?
Я бы предложил перезаписать checkEmailAction, так как, скорее всего, вы не хотите перезаписывать прослушиватель, который отправляет электронное письмо как часть вашего рабочего процесса.
Просто:
TB\UserBundle\Controller\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()]));
}
Как видите, вместо рендеринга шаблона FOS check_email я решил перенаправить пользователя в его новый профиль.
Документы о том, как перезаписать контроллер: https://symfony.com/doc/master/bundles/FOSUserBundle/overriding_controllers.html (в основном, определить родительский элемент для вашего пакета и создать файл в каталоге с тем же именем, что и FOS.)
Ответ 3
Если вы не используете письмо с подтверждением, вы можете перенаправить пользователя сразу после отправки формы регистрации следующим образом:
class RegistrationConfirmationSubscriber implements EventSubscriberInterface
{
/** @var Router */
private $router;
public function __construct(Router $router)
{
$this->router = $router;
}
public static function getSubscribedEvents()
{
return [FOSUserEvents::REGISTRATION_COMPLETED => 'onRegistrationConfirm'];
}
public function onRegistrationConfirm(FilterUserResponseEvent $event)
{
/** @var RedirectResponse $response */
$response = $event->getResponse();
$response->setTargetUrl($this->router->generate('home_route'));
}
}
Объявление абонента остается неизменным:
registration_confirmation_subscriber:
class: AppBundle\Subscriber\RegistrationConfirmationSubscriber
arguments:
- "@router"
tags:
- { name: kernel.event_subscriber }
Ответ 4
Для быстрого решения: вы также можете переопределить маршрут. Скажем, вы хотите перенаправить на свою домашнюю страницу, вы можете сделать что-то вроде этого:
/**
* @Route("/", name="index")
* @Route("/", name="fos_user_registration_confirmed")
* @Template(":Default:index.html.twig")
*/
public function indexAction()
{
Ответ 5
Перенаправление маршрута также можно использовать:
fos_user_registration_confirmed:
path: /register/confirmed
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: redirection_route
permanent: true