Sf2 : FOS UserBundle : 注册 AJAX

Posted

技术标签:

【中文标题】Sf2 : FOS UserBundle : 注册 AJAX【英文标题】:Sf2 : FOS UserBundle : registration AJAX 【发布时间】:2016-07-22 21:42:42 【问题描述】:

我正在尝试使用 AJAX 注册用户。

我在FOSUserEvents::REGISTRATION_SUCCESS上创建了一个事件监听器

所以我想知道是否已发出 AJAX 请求,但客户端的响应不满足我。

这里是我的事件监听器,注意发送的响应是一个测试,所以当然不应该有“其他”条件。

<?php

namespace SE\AppBundle\EventListener;

use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Ajax listener on FOS UserBundle registration
 */
class RegistrationListener implements EventSubscriberInterface

    private $router;

    public function __construct(RequestStack $RequestStack)
    
        $this->requestStack = $RequestStack;
    

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

    public function onRegistrationSuccess()
    

        $request = $this->requestStack->getCurrentRequest();

        if ($request->isXmlHttpRequest()) 

            $array = array( 'success' => true ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );

            return $response;

        
        else
            $array = array( 'success' => false ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );

            return $response;
        
    

services.yml:

se.app.listener.registration:
    class: SE\AppBundle\EventListener\RegistrationListener
    arguments: ["@request_stack"]
    tags:
        -  name: kernel.event_subscriber 

javascript

// Submit the request
$.ajax(
    type        : 'POST',
    url         : url,
    data        : data,
    success     : function(data, status, object) 

        console.log('success');
        console.log(data);

    ,
    error: function(data, status, object)
        console.log('error');
        console.log(data);
    
);

首先奇怪的是它进入了错误状态。

console.log(data)返回注册成功页面的DOM:

...
<p>Congrats brieuc.tribouillet7777@gmail.com, your account is now activated.</p> 
...

那么这个逻辑应该在这里还是我应该覆盖控制器?我做错了什么?

【问题讨论】:

【参考方案1】:

由于REGISTRATION_SUCCESS事件的级别,无法直接从EventListener返回响应。

您需要获取FormEvent 并修改其响应。 让我们将其作为参数传递:

class RegistrationListener implements EventSubscriberInterface

    // ...

    public function onRegistrationSuccess(FormEvent $event)
    
        $request = $this->requestStack->getCurrentRequest();

        // Prepare your response
        if ($request->isXmlHttpRequest()) 
            $array = array( 'success' => true ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );
         else 
            $array = array( 'success' => false ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );
        

        // Send it
        $event->setResponse($response);
    

它应该可以工作。

注意此事件存在无法修改响应的问题。 如果出现问题,则需要在事件订阅中设置低优先级:

public static function getSubscribedEvents()

    return [
        FOSUserEvents::REGISTRATION_SUCCESS => [
            ['onRegistrationSuccess', -10],
        ],
    ];

见#1799。

编辑

注意您应该使用 JsonResponse 而不是 json_encode 您的数据并手动设置 Content-Type

要获取表单本身及其最终错误,您可以这样做:

public function onRegistrationSuccess(FormEvent $event)

    $form = $event->getForm();

    if (count($validationErrors = $form->getErrors()) == 0) 
        return $event->setResponse(new JsonResponse(['success' => true]));
    

    // There is some errors, prepare a failure response
    $body = [];

    // Add the errors in your response body
    foreach ($validationErrors as $error) 
        $body[] = [
            'property' => $error->getPropertyPath() // The field
            'message'  => $error->getMessage() // The error message
        ];
    

    // Set the status to Bad Request in order to grab it in front (i.e $.ajax( ...).error(...))
    $response = new JsonResponse($body, 400); 
    $event->setResponse($response);

但是因为它是一个成功事件,你可能需要重写方法本身。

【讨论】:

太棒了!因此,以这种方式使用事件侦听器比覆盖该方法更好,不是吗?您是否也能在 fos 用户事件之一中捕获表单错误? 看看我的编辑 :),这完全取决于事件,我认为没有 REGISTRATION_FAILURE 事件,所以在这种情况下您可能需要覆盖该方法。

以上是关于Sf2 : FOS UserBundle : 注册 AJAX的主要内容,如果未能解决你的问题,请参考以下文章

FOS UserBundle 无法登录

Symfony 4/JMS/FOSUser:无法从 FOS\UserBundle 序列化数据

FOS UserBundle 用户管理器 - updateUser 后登录

如何自定义 FOS UserBundle URL

服务“security.authentication.manager”依赖于不存在的服务“security.user.provider.concrete.fos_userbundle”

symfony2:奏鸣曲 userbundle + fos userbundle + mongodb => 错误“sonata.user.mongodb.user_manager”不存在