Get all errors along with the fields that the error is associated with.

I use Symfony2 forms to validate POST and PUT API requests. The form processes the binding of the request data to the main object and then validates the object. Everything works very well, except for collecting errors. I use FOSRestBundle and throw a Symfony \ Component \ HttpKernel \ Exception \ HttpException with a status code of 400 and a message containing form error messages if validation fails. FOSRestBundle handles the conversion of this to a JSON response. The controller method that I have to execute is as follows (all fields fill in their errors before the form):

protected function validateEntity(AbstractType $type, $entity, Request $request)
{
    $form = $this->createForm($type, $entity);
    $form->bind($request);
    if (! $form->isValid()) {
        $message = ['Invalid parameters passed.'];
        foreach ($form->getErrors() as $error) {
            $message[] = $error->getMessage();
        }
        throw new HttpException(Codes::HTTP_BAD_REQUEST, implode("\n", $message));
    }
}

, $form- > getErrors(), , , . , POST PUT . , " ", . :

  • , , " : "
  • , , - , " "?
+4
7

getErrorsAsString , . invalid_message , This value is invalid.

+5

symfony >= 2.2

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();
    foreach ($form->getErrors() as $key => $error) {
        $template = $error->getMessageTemplate();
        $parameters = $error->getMessageParameters();

        foreach ($parameters as $var => $value) {
            $template = str_replace($var, $value, $template);
        }

        $errors[$key] = $template;
    }
    if ($form->count()) {
        foreach ($form as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    }
    return $errors;
}
+13

.

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();
    foreach ($form->getErrors() as $key => $error) {
        $template = $error->getMessageTemplate();
        $parameters = $error->getMessageParameters();

        foreach($parameters as $var => $value){
            $template = str_replace($var, $value, $template);
        }

        $errors[$key] = $template;
    }
    if ($form->hasChildren()) {
        foreach ($form->getChildren() as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    }
    return $errors;
}
+8

, :

namespace Services;

use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormErrorIterator;

/**
 * Class for converting forms.
 */
class FormConverter
{
    /**
     * Gets all errors of a form as an associative array with keys representing the dom id of the form element.
     *
     * @param Form $form
     * @param bool $deep Whether to include errors of child forms as well
     * @return array
     */
    public function errorsToArray(Form $form, $deep = false) {
        return $this->getErrors($form, $deep);
    }

    /**
     * @param Form $form
     * @param bool $deep
     * @param Form|null $parentForm
     * @return array
     */
    private function getErrors(Form $form, $deep = false, Form $parentForm = null) {
        $errors = [];

        if ($deep) {
            foreach ($form as $child) {
                if ($child->isSubmitted() && $child->isValid()) {
                    continue;
                }

                $iterator = $child->getErrors(true, false);

                if (0 === count($iterator)) {
                    continue;
                } elseif ($iterator->hasChildren()) {
                    $childErrors = $this->getErrors($iterator->getChildren()->getForm(), true, $child);
                    foreach ($childErrors as $key => $childError) {
                        $errors[$form->getName() . '_' . $child->getName() . '_' .$key] = $childError;
                    }
                } else {
                    foreach ($iterator as $error) {
                        $errors[$form->getName() . '_' . $child->getName()][] = $error->getMessage();
                    }
                }
            }
        } else {
            $errorMessages = $this->getErrorMessages($form->getErrors(false));
            if (count($errorMessages) > 0) {
                $formName = $parentForm instanceof Form ? $parentForm->getName() . '_' . $form->getName() : $form->getName();
                $errors[$formName] = $errorMessages;
            }
        }

        return $errors;
    }

    /**
     * @param FormErrorIterator $formErrors
     * @return array
     */
    private function getErrorMessages(FormErrorIterator $formErrors) {
        $errorMessages = [];
        foreach ($formErrors as $formError) {
            $errorMessages[] = $formError->getMessage();
        }

        return $errorMessages;
    }
}
+1

, , .
Symfony 4 ( , , , , , , , ajax: :)

, dom, Symfony ( )

//file FormErrorsSerializer.php
<?php

namespace App\Helper;

use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormErrorIterator;

class FormErrorsSerializer
{
    public function getFormErrors(Form $form): array
    {
        return $this->recursiveFormErrors($form->getErrors(true, false), [$form->getName()]);
    }

    private function recursiveFormErrors(FormErrorIterator $formErrors, array $prefixes): array
    {
        $errors = [];

        foreach ($formErrors as $formError) {
            if ($formError instanceof FormErrorIterator) {
                $errors = array_merge($errors, $this->recursiveFormErrors($formError, array_merge($prefixes, [$formError->getForm()->getName()])));
            } elseif ($formError instanceof FormError) {
                $errors[implode('_', $prefixes)][] = $formError->getMessage();
            }
        }

        return $errors;
    }
}
+1

Symfony 4. x+ ( ).

// $form = $this->createForm(SomeType::class);
// $form->submit($data);
// if (!$form->isValid()) {
//     var_dump($this->getErrorsFromForm($form));
// }

private function getErrorsFromForm(FormInterface $form, bool $child = false): array
{
    $errors = [];

    foreach ($form->getErrors() as $error) {
        if ($child) {
            $errors[] = $error->getMessage();
        } else {
            $errors[$error->getOrigin()->getName()][] = $error->getMessage();
        }
    }

    foreach ($form->all() as $childForm) {
        if ($childForm instanceof FormInterface) {
            if ($childErrors = $this->getErrorsFromForm($childForm, true)) {
                $errors[$childForm->getName()] = $childErrors;
            }
        }
    }

    return $errors;
}
0

All Articles