Get all errors along with fields the error is connected to

前端 未结 7 1378
予麋鹿
予麋鹿 2021-01-03 06:43

I\'m using Symfony2 forms to validate POST and PUT requests to an API. The form handles binding the request data to the underlying entity and then validating the entity. Eve

相关标签:
7条回答
  • 2021-01-03 07:06

    For Symfony 4.x+ (may working with lower versions).

    // $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 讨论(0)
  • 2021-01-03 07:08

    You can take getErrorsAsString method as an example to get the functionality you want. Also you have to set invalid_message option on the form field to change This value is invalid message.

    0 讨论(0)
  • 2021-01-03 07:13

    I created a bundle to help with this issue.

    You can get it here:

    https://github.com/Ex3v/FormErrorsBundle

    Contributions are welcome. Cheers.

    0 讨论(0)
  • 2021-01-03 07:13

    I needed a solution to get an associative array of all errors of all nested forms with the key formated so it represents the document id of the corresponding form field element:

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-03 07:24

    Tried everything, nothing worked as I wanted.
    Here is my attempt with Symfony 4 (also why the hell isn't this available by default in the framework is beyond me, it's like they dont want us to use forms with ajax :thinking:)

    It returns a messages array, with the keys being the dom id as it would be generated by Symfony (it works with arrays as well)

    //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;
        }
    }
    
    0 讨论(0)
  • 2021-01-03 07:26

    Use this function to get all error messages after binding form.

    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;
    }
    
    0 讨论(0)
提交回复
热议问题