Get all errors along with fields the error is connected to

蓝咒 提交于 2019-11-30 15:57:38
Mun Mun Das

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.

and for 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;
}
Julfiker

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;
}

I created a bundle to help with this issue.

You can get it here:

https://github.com/Ex3v/FormErrorsBundle

Contributions are welcome. Cheers.

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;
    }
}

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;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!