[英]how to return json encoded form errors in symfony
I want to create a webservice to which I submit a form, and in case of errors, returns a JSON encoded list that tells me which field is wrong.我想创建一个我提交表单的网络服务,如果出现错误,则返回一个 JSON 编码的列表,告诉我哪个字段是错误的。
currently I only get a list of error messages but not an html id or a name of the fields with errors目前我只得到一个错误消息列表,而不是一个 html id 或有错误的字段的名称
here's my current code这是我当前的代码
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;
}
this will give me a response like这会给我一个回应
{
"status":400,
"errorMsg":"Bad Request",
"errorReport":{
"Task cannot be blank",
"Task date needs to be within the month"
}
}
but what I really want is something like但我真正想要的是
{
"status":400,
"errorMsg":"Bad Request",
"errorReport":{
"taskfield" : "Task cannot be blank",
"taskdatefield" : "Task date needs to be within the month"
}
}
How can I achieve that?我怎样才能做到这一点?
I am using this, it works quiet well:我正在使用它,它运行良好:
/**
* 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;
}
I've finally found the solution to this problem here , it only needed a small fix to comply to latest symfony changes and it worked like a charm:我终于在这里找到了这个问题的解决方案,它只需要一个小的修复来符合最新的 symfony 更改,它就像一个魅力:
The fix consists in replacing line 33修复包括替换第 33 行
if (count($child->getIterator()) > 0) {
with和
if (count($child->getIterator()) > 0 && ($child instanceof \Symfony\Component\Form\Form)) {
because, with the introduction in symfony of Form\\Button, a type mismatch will occur in serialize function which is expecting always an instance of Form\\Form.因为,随着 symfony 中 Form\\Button 的引入,序列化函数中会发生类型不匹配,该函数总是期望 Form\\Form 的实例。
You can register it as a service:您可以将其注册为服务:
services:
form_serializer:
class: Wooshii\SiteBundle\FormErrorsSerializer
and then use it as the author suggest:然后按照作者的建议使用它:
$errors = $this->get('form_serializer')->serializeFormErrors($form, true, true);
This does the trick for me这对我有用
$errors = [];
foreach ($form->getErrors(true, true) as $formError) {
$errors[] = $formError->getMessage();
}
PHP has associative arrays, meanwhile JS has 2 different data structures : object and arrays. PHP 有关联数组,而 JS 有两种不同的数据结构:对象和数组。
The JSON you want to obtain is not legal and should be :您要获取的 JSON 不合法,应该是:
{
"status":400,
"errorMsg":"Bad Request",
"errorReport": {
"taskfield" : "Task cannot be blank",
"taskdatefield" : "Task date needs to be within the month"
}
}
So you may want to do something like this to build your collection :所以你可能想要做这样的事情来建立你的收藏:
$errorCollection = array();
foreach($errors as $error){
$errorCollection[$error->getId()] = $error->getMessage();
}
(assuming the getId() method exist on $error objects) (假设 $error 对象上存在 getId() 方法)
By reading other people's answers I ended up improving it to my needs.通过阅读其他人的答案,我最终根据自己的需要对其进行了改进。 I use it in Symfony 3.4.
我在 Symfony 3.4 中使用它。
To be used in a controller like this:要在这样的控制器中使用:
$formErrors = FormUtils::getErrorMessages($form);
return new JsonResponse([
'formErrors' => $formErrors,
]);
With this code in a separate Utils class在单独的 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;
}
}
This will do the trick.这将解决问题。 This static method runs recursively through the
Symfony\\Component\\Form\\FormErrorIterator
delivered by calling $form->getErrors(true, false)
.这个静态方法通过调用
$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;
}
}
Here is the 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."
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.