Symfony 3:FOSSUserBundle得到一个JsonResponse而不是重定向

On my Symnfony3 project I noticed that during registration some events are generated where I can override the response. eg. Instead of rendering the default twig template and redirect to just return a JsonResponse with a successMessage.

Therefore I did the following Event Subscriber:

namespace AppBundle\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use AppBundle\Constants\AjaxJsonResponseConstants;
use Symfony\Component\HttpFoundation\JsonResponse;
use FOS\UserBundle\Event\FilterUserResponseEvent;

class UserRegistrationResponseChanger implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        $subscribedEvents=[
//              FOSUserEvents::REGISTRATION_INITIALIZE=>[],
                FOSUserEvents::REGISTRATION_COMPLETED=>[],
                FOSUserEvents::REGISTRATION_SUCCESS=>["setJsonResponseOnSuccess",-1],
                FOSUserEvents::REGISTRATION_FAILURE=>["setJsonResponseOnFailure",-1],
//              FOSUserEvents::REGISTRATION_CONFIRM=>[],
//              FOSUserEvents::REGISTRATION_CONFIRMED=>[]
        ];
    }

    public function setJsonResponseOnSuccess(FormEvent $formEvent)
    {
        $response=['status'=>AjaxJsonResponseConstants::AJAX_ACTION_SUCCESS,'message'=>"User Sucessfully Registered please check your mail."];
        $response=new JsonResponse($response);
        $formEvent->setResponse($response);

        return $response;
    }

    public function setJsonResponseOnFailure(FormEvent $formEvent)
    {
        $response=['status'=>AjaxJsonResponseConstants::AJAX_ACTION_FAIL,'message'=>"You cannot register please try again later"];
        $response=new JsonResponse($response);
        $formEvent->setResponse($response);

        return $response;
    }
}

Also on my services.yml I have put the following:

 app.user_register.subscriber:
  class: AppBundle\EventSubscriber\UserRegistrationResponseChanger
  tags:
   - { name: app.user_register.subscriber }

And the command

In order to override on how the response will get returned but somehow it fails to do so and redirects to the default page. What I try to acheive it to perform the registration via ajax call instead of rendering the registration page and redirecting.

You should do this steps:

First of all you should use kernel.event_subscriber instead of app.user_register.subscriber when you define the event subscriber therfore your subscriber will be defined like that:

 app.user_register.subscriber:
  class: AppBundle\EventSubscriber\UserRegistrationResponseChanger
  tags:
   - { name: kernel.event_subscriber }

To the services.yml.

Furthermore the getSubscribedEvents must return the array of the listeners. Also the FOSUserEvents::REGISTRATION_COMPLETED MUST Have a listener even if it isdoes not have an implementation, if you do not want a listener just comment the like.

In the end your listener shuld be implemented like that:

namespace AppBundle\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use AppBundle\Constants\AjaxJsonResponseConstants;
use Symfony\Component\HttpFoundation\JsonResponse;
use FOS\UserBundle\Event\FilterUserResponseEvent;

class UserRegistrationResponseChanger implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        $subscribedEvents=[
//              FOSUserEvents::REGISTRATION_INITIALIZE=>[],
//              FOSUserEvents::REGISTRATION_COMPLETED=>[],
                FOSUserEvents::REGISTRATION_SUCCESS=>["setJsonResponseOnSuccess",-1],
                FOSUserEvents::REGISTRATION_FAILURE=>["setJsonResponseOnFailure",-1],
//              FOSUserEvents::REGISTRATION_CONFIRM=>[],
//              FOSUserEvents::REGISTRATION_CONFIRMED=>[]
        ];

        return $subscribedEvents;
    }

    public function setJsonResponseOnSuccess(FormEvent $formEvent)
    {
        $response=['status'=>AjaxJsonResponseConstants::AJAX_ACTION_SUCCESS,'message'=>"User Sucessfully Registered please check your mail."];
        $response=new JsonResponse($response);
        $formEvent->setResponse($response);

        return $response;
    }

    public function setJsonResponseOnFailure(FormEvent $formEvent)
    {
        $response=['status'=>AjaxJsonResponseConstants::AJAX_ACTION_FAIL,'message'=>"You cannot register please try again later"];
        $response=new JsonResponse($response);
        $formEvent->setResponse($response);

        return $response;
    }
}

You should prioritize the REGISTRATION_SUCCESS event when you have registration confirmation (default behaviour in FOSUserBundle), see http://symfony.com/doc/master/bundles/FOSUserBundle/controller_events.html#registration-success-listener-with-enabled-confirmation-at-the-same-time

The service definition needs to be like this:

#app/config/services.yml
app.security_registration_success:
    class: Path\To\Your\EventListener\RegistrationSuccessListener
    tags:
        - { name: kernel.event_subscriber }

An example of a registration success listener:

<?php

declare(strict_types=1);

namespace Path\To\Your\EventListener;

use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;

class RegistrationSuccessListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [FOSUserEvents::REGISTRATION_SUCCESS => [['onRegistrationSuccess', -10]]];
    }

    public function onRegistrationSuccess(FormEvent $event): void
    {
        $event->setResponse(new JsonResponse());
    }
}