【问题标题】:How to use a JsonResponse with ajax如何将 JsonResponse 与 ajax 一起使用
【发布时间】:2016-03-08 05:47:28
【问题描述】:

我正在使用 Symfony2 并执行 Ajax 调用来处理表单。我遇到的问题是,通过使用返回给我的JsonResponse,驱动程序告诉我该值未定义。我想知道我在解决这个问题方面做错了什么,以及是否可以以某种方式将错误返回到表单字段以从 Ajax 验证可以在不刷新页面的情况下在表单中显示失败。

控制器:

public function createAction(Request $request){

$entity = new Student();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);

if ($form->isValid()) {
    $em = $this->getDoctrine()->getManager();
    $em->persist($entity);
    $em->flush();

    return new JsonResponse(array('message' => 'Success!'), 200);
 }

    return $this->render('BackendBundle:Student:new.html.twig', array(
    'entity' => $entity,
    'form'   => $form->createView(),
 ));
}

Ajax 调用:

$('.form_student').submit(function(event) {
 event.preventDefault();

  $.ajax({
  type: 'POST',
  url: Routing.generate('student_create'),
  data: $(this).serialize(),

  success: function(response) {

    alert(response.message);

  },
  error: function (xhr, desc, err){

    alert("error");
  }
 })
  return false;
});

【问题讨论】:

  • 你试过调试它吗?尝试在 createAction 方法的第一行执行echo json_encode(['message' => 'success']; exit
  • 嗨@Robert,请原谅我的无知,因为我是新手,我将echo json_encode(['message' => 'success']; 放在 createAction 方法的第一行并给了我错误。是你的意思吗?
  • 不,他的意思是将return new JsonResponse(array('message' => 'Success!'), 200); 更改为echo new JsonResponse(array('message' => 'Success!'), 200); exit;。然后是正确的你的网址url: Routing.generate('student_create')
  • 嗨@hendrathings,我试过你说的,未定义的值仍然存在,AJAX调用执行成功但不知道,因为没有获得响应的值。网址正确。

标签: javascript php jquery ajax symfony


【解决方案1】:

您需要以不同于常规 HTML 请求的方式处理 XMLHttpRequest。

目前,当发出 XMLHttpRequest 但表单失败时,会再次呈现整个页面(带有“成功”状态代码),但您只想返回带有消息和“失败”状态代码的响应。

以下内容应该对您有所帮助。

public function createAction(Request $request)
{
    // if request is XmlHttpRequest (AJAX) but not a POSt, throw an exception
    if ($request->isXmlHttpRequest() && !$request->isMethod(Request::METHOD_POST)) {
        throw new HttpException('XMLHttpRequests/AJAX calls must be POSTed');
    }

    $entity = new Student();
    $form = $this->createCreateForm($entity);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();

        // if the form was successful and the call was an AJAX request
        // respond with a JSON Response (with a 201/created status code)
        if ($request->isXmlHttpRequest()) {
            return new JsonResponse(array('message' => 'Success!'), 201);
        }

        // If the form was successful and the call was HTTP
        // redirect to "show student"
        return $this->redirect('student_show', array('id' => $entity->getId()));
    }

    // if request was an AJAX call and (obviously) the form was not valid
    // return message about form failure
    // (with a 400/Bad Request status code)
    if ($request->isMethod(Request::METHOD_POST)) {
        return new JsonResponse(array('message' => 'failed due to form errors'), 400);
        // you could also loop through the form errors to create an array, use a custom 
        // form -> errors array transformer or use the @fos_rest.view_handler to output
        // your form errors
    }

    return $this->render('BackendBundle:Student:new.html.twig', array(
        'entity' => $entity,
        'form'   => $form->createView(),
    ));
}

更新

javascript应该像这样工作。

$('.form_student').submit(function(event) {
    event.preventDefault();

    $.ajax({
        type: 'POST',
        url: Routing.generate('student_create'),
        data: $(this).serialize(),
        dataType: 'json',

        // if "student_create" returns a 2** status code
        success: function(response) {
            // should return "Success!"
            alert(response.message);
        },

        // if "student_create" returns a non-2** status code
        error: function (xhr, desc, err){
            // if the response was parsed to json and has a message key
            if (xhr.responseJSON && xhr.responseJSON.message) {
                alert(xhr.responseJSON.message);
            // otherwise use the status text
            } else {
                alert(desc);
            }
        }
    });

    return false;
});

【讨论】:

  • 嗨@qooplmao,首先感谢您的回答。我了解您向我指出的一切,但我必须使用 AJAX 响应的问题,因为我没有得到正确的消息。您能否给我添加一个带有示例的 ajax 代码,看看我可能会失败吗?
  • 我已经注释了你的代码。这更有意义吗?
  • 嗨@qooplmao,我一直在尝试更改您之前告诉我的内容,但我收到第一个 METHOD_POST 错误,表明它未定义。错误:/opt/lampp/htdocs/Symfony/src/BackendBundle/Controller/StudentController.php 第 40 行中未定义的类常量 'METHOD_POST' h2> 删除此代码我设法得到带有错误消息的 400 错误(I'已经在控制台上看到了)以他现在向我指示的方式。
  • $request->isMethod(Request::METHOD_POST) 和 $request->isMethod('POST') 一样吗?我改变了它,但现在总是向我显示错误消息并且从未成功执行 ajax 调用,尽管您在表单中输入了正确的值。
  • 是的,Request::METHOD_POST 只使用常量,但它仅适用于 2.6+,因此您可能没有,具体取决于您的版本。我真的不知道你问题的其余部分是什么意思。对不起。
【解决方案2】:

使用ajax,返回不起作用

return new JsonResponse(array('message' => 'Success!'), 200);

您应该使用 PHP echo 打印该值,以便在 ajax 成功回调中使用它,例如

echo new JsonResponse(array('message' => 'Success!'), 200);

【讨论】:

  • 这个答案很好,我就不新了。但是你让你的回调done 得到响应
  • 嗨@SidneyLiebrand,我仍然认为该值未定义。
  • @Thomas, success() 也会这样做。
  • @NiranjanNRaju 几乎相同,success 仅在返回的请求的 http 状态为 200 时触发,否则将调用 faildone 在每个请求结束时调用无论失败或成功。
  • 这是不正确的。该操作需要返回响应,而不是回显 JSONResponse。回显它只是意味着它将响应(状态代码、标题和内容)打印为字符串,然后继续返回后一个响应。
【解决方案3】:

你需要有两个动作:

1。动作表演

显示操作应处理表单的界面。例如:

public function showAction(Request $request){

    $entity = new Student();
    $form = $this->createCreateForm($entity);

    return $this->render('BackendBundle:Student:new.html.twig', array(
        'entity' => $entity,
        'form'   => $form->createView(),
    ));
}

2。动作句柄保存

通过 ajax 请求保存数据时应处理动作保存。例如:

public function createAction(Request $request)
{
    //get all data post
    $data = $request->request->all();
    extract($data, EXTR_PREFIX_SAME, "wddx");
    // if you want to see the result uncoment below
    // dump($data); // uncomment this to see data

    //$id = $data['id'];
    //$name = $data['name'];

    $student = new Student();
    //$student->.... = ... // set your field
    //...
    //...


    try {
        // try save entity
        $em = $this->getDoctrine()->getManager();
        $em->persist($student);
        $em->flush();
    } catch (\Exception $e) {
        // set your error message ...
    }
}

注意:

记得更改url: Routing.generate('student_create')指向保存句柄

【讨论】: