FOSUserBundle : Redirect the user after register w

2019-01-11 19:26发布

I want to redirect the user to another form just after registration, before he could access to anything on my website (like in https://github.com/FriendsOfSymfony/FOSUserBundle/issues/387).

So I create an eventListener like in the doc :

<?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 }

But it doesn't work, the user register, he click on the confirmation link in his mailbox, he is not redirected on the page I want, he is logged and I just have the message who said the account is confirmed.

Why it doesn't redirect me to the route : rsWelcomeBundle_check_full_register like I want ?

Thanks

5条回答
Juvenile、少年°
2楼-- · 2019-01-11 19:45

Route redirection can also be used:

fos_user_registration_confirmed:
    path: /register/confirmed
    defaults:
        _controller: FrameworkBundle:Redirect:redirect
        route: redirection_route
        permanent: true
查看更多
手持菜刀,她持情操
3楼-- · 2019-01-11 19:57

To accomplish what you want, you should use FOSUserEvents::REGISTRATION_CONFIRM instead of FOSUserEvents::REGISTRATION_CONFIRMED.

You then have to rewrite rewrite your class RegistrationConfirmedListener like:

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));
    }
}

And your service.yml:

services:
    rs_user.registration_complet:
        class: rs\UserBundle\EventListener\RegistrationConfirmListener
        arguments: [@router]
        tags:
            - { name: kernel.event_subscriber }

REGISTRATION_CONFIRM receives a FOS\UserBundle\Event\GetResponseUserEvent instance as you can see here: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/FOSUserEvents.php

It allows you to modify the response that will be sent: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Event/GetResponseUserEvent.php

查看更多
The star\"
4楼-- · 2019-01-11 19:59
"friendsofsymfony/user-bundle": "2.0.x-dev",

Not sure why the accepted answer works for you as REGISTRATION_CONFIRM happens after the token is confirmed.

In case you want to perform an action, redirect to another page with some additional form after the FOS registerAction I would suggest the following way.

This is the code that is performed on registerAction once the submitted form is valid by 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;
        }

As you can see the first possible return happens after FOSUserEvents::REGISTRATION_SUCCESS event in case the response is null which in my case doesn't as I have configured a mailer to send a confirmation token and FOS is using an listener that listens to this FOSUserEvents::REGISTRATION_SUCCESS event and after sending an email it sets a redirect response.

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));
}

Okay I understand! So how do I redirect to another page?

I would suggest to overwrite checkEmailAction as most likely you don't want to overwrite the listener that sends an email as that's part of your workflow.

Simply:

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()]));
}

As you can see instead of rendering FOS's check_email template I decided to redirect user to his new profile.

Docs how to overwrite an controller: https://symfony.com/doc/master/bundles/FOSUserBundle/overriding_controllers.html (basically define a parent for your bundle and create a file in the directory with the same name as FOS does.)

查看更多
Anthone
5楼-- · 2019-01-11 20:03

If you're not using a confirmation email, you can redirect the user right after submiting the registration form this way :

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'));
    }
}

The subscriber declaration stay the same :

registration_confirmation_subscriber:
    class: AppBundle\Subscriber\RegistrationConfirmationSubscriber
    arguments:
        - "@router"
    tags:
        - { name: kernel.event_subscriber }
查看更多
Rolldiameter
6楼-- · 2019-01-11 20:05

For a quick solution: you can also override the route. Let's say you want to redirect to your homepage you can do something like this:

 /**
 * @Route("/", name="index")
 * @Route("/", name="fos_user_registration_confirmed")
 * @Template(":Default:index.html.twig")
 */
public function indexAction()
{
查看更多
登录 后发表回答