how to return json encoded form errors in symfony
Solution 1
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:
The fix consists in replacing line 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.
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);
Solution 2
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;
}
Solution 3
This does the trick for me
$errors = [];
foreach ($form->getErrors(true, true) as $formError) {
$errors[] = $formError->getMessage();
}
Solution 4
PHP has associative arrays, meanwhile JS has 2 different data structures : object and arrays.
The JSON you want to obtain is not legal and should be :
{
"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)
Related videos on Youtube
SimonQuest
Updated on June 07, 2022Comments
-
SimonQuest almost 2 years
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.
currently I only get a list of error messages but not an html id or a name of the fields with errors
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?
-
SimonQuest almost 10 yearsfor id or name of the field I mean something that I can use to target the field in form... like an html id or name of the field.
-
Delapouite almost 10 yearsIf your iterate with foreach($errors as $key => $error), isn't $key what you're looking for?
-
SimonQuest almost 10 yearsno, it would simply be a numerical index... I need something to target the html element
-
rolebi almost 10 years@SimonQuest This answer (and subsequent) may help you.
-
SimonQuest almost 10 yearsUnfortunately this didn't work for me, at least not the way I wanted. Thanks you very much for answering
-
SimonQuest almost 10 yearsit doesn't traverse properly the form structure if it's not a simple one and it's not returning the input fields ids/names. Maybe My explanation of the problem wasn't clear enough. Try the solution I've found, you'll understand.
-
COil almost 10 yearsYes indeed, it's for one level forms only.
-
Yonedev over 5 yearsPerfect solution :)