如何在 symfony 中返回 json 编码格式错误
Posted
技术标签:
【中文标题】如何在 symfony 中返回 json 编码格式错误【英文标题】:how to return json encoded form errors in symfony 【发布时间】:2014-08-24 17:17:05 【问题描述】:我想创建一个向其提交表单的 Web 服务,如果出现错误,则返回一个 JSON 编码列表,告诉我哪个字段是错误的。
目前我只得到错误消息列表,但没有 html id 或有错误的字段名称
这是我当前的代码
public function saveAction(Request $request)
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new TaskType(), new Task());
$form->handleRequest($request);
$task = $form->getData();
if ($form->isValid())
$em->persist($task);
$em->flush();
$array = array( 'status' => 201, 'msg' => 'Task Created');
else
$errors = $form->getErrors(true, true);
$errorCollection = array();
foreach($errors as $error)
$errorCollection[] = $error->getMessage();
$array = array( 'status' => 400, 'errorMsg' => 'Bad Request', 'errorReport' => $errorCollection); // data to return via JSON
$response = new Response( json_encode( $array ) );
$response->headers->set( 'Content-Type', 'application/json' );
return $response;
这会给我一个类似的回应
"status":400,
"errorMsg":"Bad Request",
"errorReport":
"Task cannot be blank",
"Task date needs to be within the month"
但我真正想要的是类似的东西
"status":400,
"errorMsg":"Bad Request",
"errorReport":
"taskfield" : "Task cannot be blank",
"taskdatefield" : "Task date needs to be within the month"
我怎样才能做到这一点?
【问题讨论】:
【参考方案1】:我正在使用它,它运行良好:
/**
* List all errors of a given bound form.
*
* @param Form $form
*
* @return array
*/
protected function getFormErrors(Form $form)
$errors = array();
// Global
foreach ($form->getErrors() as $error)
$errors[$form->getName()][] = $error->getMessage();
// Fields
foreach ($form as $child /** @var Form $child */)
if (!$child->isValid())
foreach ($child->getErrors() as $error)
$errors[$child->getName()][] = $error->getMessage();
return $errors;
【讨论】:
不幸的是,这对我不起作用,至少不是我想要的方式。非常感谢您的回答 如果它不是一个简单的表单结构并且它没有返回输入字段 ids/names,它就不会正确地遍历表单结构。也许我对问题的解释不够清楚。试试我找到的解决方案,你就会明白了。 是的,它只适用于一级表单。 完美解决方案:)【参考方案2】:我终于找到了这个问题的解决方案here,它只需要一个小修复来符合最新的 symfony 更改,它就像一个魅力:
修复包括替换第 33 行
if (count($child->getIterator()) > 0)
与
if (count($child->getIterator()) > 0 && ($child instanceof \Symfony\Component\Form\Form))
因为在 symfony 中引入 Form\Button 时,序列化函数会出现类型不匹配,该函数总是期望 Form\Form 的实例。
您可以将其注册为服务:
services:
form_serializer:
class: Wooshii\SiteBundle\FormErrorsSerializer
然后按照作者的建议使用它:
$errors = $this->get('form_serializer')->serializeFormErrors($form, true, true);
【讨论】:
【参考方案3】:这对我有用
$errors = [];
foreach ($form->getErrors(true, true) as $formError)
$errors[] = $formError->getMessage();
【讨论】:
【参考方案4】:php 有关联数组,而 JS 有两种不同的数据结构:对象和数组。
你要获取的 JSON 是不合法的,应该是:
"status":400,
"errorMsg":"Bad Request",
"errorReport":
"taskfield" : "Task cannot be blank",
"taskdatefield" : "Task date needs to be within the month"
所以你可能想做这样的事情来建立你的收藏:
$errorCollection = array();
foreach($errors as $error)
$errorCollection[$error->getId()] = $error->getMessage();
(假设 $error 对象上存在 getId() 方法)
【讨论】:
对于字段的 id 或名称,我的意思是我可以用它来定位表单中的字段...例如 html id 或字段名称。 如果您使用 foreach($errors as $key => $error) 进行迭代,您要查找的不是 $key 吗? 不,它只是一个数字索引...我需要一些东西来定位 html 元素 @SimonQuest 这个answer(及后续)可能会对您有所帮助。【参考方案5】:通过阅读其他人的答案,我最终根据自己的需要对其进行了改进。我在 Symfony 3.4 中使用它。
在这样的控制器中使用:
$formErrors = FormUtils::getErrorMessages($form);
return new JsonResponse([
'formErrors' => $formErrors,
]);
在单独的 Utils 类中使用此代码
<?php
namespace MyBundle\Utils;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
class FormUtils
/**
* @param FormInterface $form
* @return array
*/
public static function getErrorMessages(FormInterface $form)
$formName = $form->getName();
$errors = [];
/** @var FormError $formError */
foreach ($form->getErrors(true, true) as $formError)
$name = '';
$thisField = $formError->getOrigin()->getName();
$origin = $formError->getOrigin();
while ($origin = $origin->getParent())
if ($formName !== $origin->getName())
$name = $origin->getName() . '_' . $name;
$fieldName = $formName . '_' . $name . $thisField;
/**
* One field can have multiple errors
*/
if (!in_array($fieldName, $errors))
$errors[$fieldName] = [];
$errors[$fieldName][] = $formError->getMessage();
return $errors;
【讨论】:
【参考方案6】:这样就可以了。此静态方法通过调用$form->getErrors(true, false)
传递的Symfony\Component\Form\FormErrorIterator
递归运行。
<?php
namespace App\Utils;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormErrorIterator;
class FormUtils
public static function generateErrorsArrayFromForm(FormInterface $form)
$result = [];
foreach ($form->getErrors(true, false) as $formError)
if ($formError instanceof FormError)
$result[$formError->getOrigin()->getName()] = $formError->getMessage();
elseif ($formError instanceof FormErrorIterator)
$result[$formError->getForm()->getName()] = self::generateErrorsArrayFromForm($formError->getForm());
return $result;
结果如下:
"houseworkSection": "All the data of the housework section must be set since the section has been requested.",
"foodSection":
"requested":
"requested": "This value is not valid."
【讨论】:
以上是关于如何在 symfony 中返回 json 编码格式错误的主要内容,如果未能解决你的问题,请参考以下文章
最佳实践以及如何在 Symfony2 中找到从 iOS AFNetworking 获取 POST 数据并在 GET 中返回 JSON?