Symfony2: Как получить ошибки проверки формы после привязки запроса к форме

110

Вот мой saveActionкод (где форма передает данные)

public function saveAction()
{
    $user = OBUser();

    $form = $this->createForm(new OBUserType(), $user);

    if ($this->request->getMethod() == 'POST')
    {
        $form->bindRequest($this->request);
        if ($form->isValid())
            return $this->redirect($this->generateUrl('success_page'));
        else
            return $this->redirect($this->generateUrl('registration_form'));
    } else
        return new Response();
}

У меня вопрос: как мне получить сообщение об ошибке при $form->isValid()возврате false?

путоларуан
источник

Ответы:

117

У вас есть два возможных способа сделать это:

  • не перенаправлять пользователя при ошибке и не отображать {{ form_errors(form) }}в файле шаблона
  • доступ к массиву ошибок как $form->getErrors()
nefo_x
источник
22
Я сделал второе, что вы предложили, но form-> getErrors () вернул пустой массив.
putolaruan 08
2
Я также сделал первый (с шаблонами php <? Php echo $ view ['form'] -> errors ($ form)?>), Но он все еще пуст!
putolaruan 08
59
@mives Вы должны установить error_bubblingзначение true в вашем типе формы, явно установив параметр для каждого поля.
kgilden
5
Если вы используете собственные валидаторы, Symfony не возвращает ошибки, сгенерированные этими валидаторами в $ form-> getErrors ().
Джей Шет
13
Вы также $form->getErrors(true)можете включить ошибки дочерних форм
Крис,
103

Symfony 2.3 / 2.4:

Эта функция получает все ошибки. Те, которые указаны в форме, такие как «Токен CSRF недействителен. Попробуйте повторно отправить форму». а также дополнительные ошибки в дочерних формах, у которых нет пузырей ошибок.

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();

    foreach ($form->getErrors() as $key => $error) {
        if ($form->isRoot()) {
            $errors['#'][] = $error->getMessage();
        } else {
            $errors[] = $error->getMessage();
        }
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = $this->getErrorMessages($child);
        }
    }

    return $errors;
}

Чтобы получить все ошибки в виде строки:

$string = var_export($this->getErrorMessages($form), true);

Symfony 2.5 / 3.0:

$string = (string) $form->getErrors(true, false);

Документы:
https://github.com/symfony/symfony/blob/master/UPGRADE-2.5.md#form https://github.com/symfony/symfony/blob/master/UPGRADE-3.0.md#form (на дно: The method Form::getErrorsAsString() was removed)

кувырок
источник
1
Это выглядит как наиболее правильный ответ для текущей версии Symfony 2.4.
Слава Фомин II
@Flip It Works отлично работает на 2.5
iarroyo
1
Отличный ответ, НО вызывало$errors[$child->getName()] = $this->getErrorMessages($child); исключение, поскольку getErrorMessages отсутствовало в компоненте Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller . Поэтому я заменил его на$form_errors[$child->getName()] = $child->getErrorsAsString();
Ахад Али
3
@AhadAli - это рекурсивная функция, поэтому, когда вы помещаете фрагмент кода в класс, где вам нужна эта функция, он сможет вызывать сам себя. Ваше «исправление» не позволит вам добраться до вложенных форм. Это сработало для 37 других людей, это должно сработать и для вас;)
Flip
@Flip Ах, извините, я плохо, я только смотрел $this->getErrorMessages()и думал, что он вызывается непосредственно внутри контроллера и является частью Symfony api.
Ахад Али
47

Ниже приведено решение, которое сработало для меня. Эта функция находится в контроллере и возвращает структурированный массив всех сообщений об ошибках и поля, вызвавшего их.

Symfony 2.0:

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

Symfony 2.1 и новее:

private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();

    if ($form->hasChildren()) {
        foreach ($form->getChildren() as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    } else {
        foreach ($form->getErrors() as $key => $error) {
            $errors[] = $error->getMessage();
        }   
    }

    return $errors;
}
Icode4food
источник
5
Gist.github.com/2011671 улучшен, но все еще не то, что я хочу. Я хочу, чтобы ключи массива были именами полей, но это не так.
umpirsky
9
@SalmanPK Twig нигде не упоминается в приведенном выше коде. Не думаю, что понимаю ваш комментарий.
Icode4food
1
Вот исправление предыдущей сути, это работает в Symfony 2.1.7. gist.github.com/WishCow/5101428
К. Норберт
Похоже, что в вашем образце в Symfony2.1 $this->getFormErrorsдолжна быть опечатка$this->getErrorMessages
Мик,
@umpirsky Чтобы получить имя поля, я получил следующее: $ child-> getConfig () -> getOptions () ['label'] Мне
потребовалась
35

Используйте валидатор, чтобы получить ошибки для определенного объекта

if( $form->isValid() )
{
    // ...
}
else
{
    // get a ConstraintViolationList
    $errors = $this->get('validator')->validate( $user );

    $result = '';

    // iterate on it
    foreach( $errors as $error )
    {
        // Do stuff with:
        //   $error->getPropertyPath() : the field that caused the error
        //   $error->getMessage() : the error message
    }
}

Справка по API:

Оливье 'Олбаум' Шерлер
источник
Спасибо, что мне понадобилось +1
Фил Паффорд
4
Я не уверен, что это хороший подход - проверять каждую сущность отдельно. Что делать, если у вас сложная иерархическая форма? Вторая проблема заключается в том, что проверка выполняется дважды.
Слава Фомин II
3
@SlavaFominII - «Вторая проблема заключается в том, что проверка выполняется дважды» - Хороший момент, ничего не обновляется! Тот же список ошибок после!
BentCoder
20

Чтобы получить правильные (переводимые) сообщения, в настоящее время использующие SF 2.6.3, вот моя последняя функция (поскольку ни одна из вышеперечисленных, похоже, больше не работает):

 private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();
    foreach ($form->getErrors(true, false) as $error) {
        // My personnal need was to get translatable messages
        // $errors[] = $this->trans($error->current()->getMessage());
        $errors[] = $error->current()->getMessage();
    }

    return $errors;
}

поскольку метод Form :: getErrors () теперь возвращает экземпляр FormErrorIterator , если вы не переключите второй аргумент ($ flatten) на true . (Затем он вернет экземпляр FormError , и вам нужно будет вызвать метод getMessage () напрямую, без метода current ():

 private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();
    foreach ($form->getErrors(true, true) as $error) {
        // My personnal need was to get translatable messages
        // $errors[] = $this->trans($error->getMessage());
        $errors[] = $error->getMessage();
    }

    return $errors;
}

)

Самое главное - установить для первого аргумента значение true, чтобы получать ошибки. Если оставить для второго аргумента ($ flatten) значение по умолчанию ( true ), будут возвращены экземпляры FormError , тогда как он вернет FormErrorIterator. при установке значения false - экземпляры .

Cedo
источник
Хороший, используя то же самое.
Damaged Organic
не так ли? :) @KidBinary
Cedo
Абсолютно великолепно, приятель
:)
Лучший вариант: $ errors = array_map (function ($ item) {return $ item-> current () -> getMessage ();}, $ campaignForm-> getErrors (true, false));
Enrique Quero
Хорошее решение для Symfony 2.7
Ян Чабот
16

Для моих флеш-сообщений я был доволен $form->getErrorsAsString()

Изменить (от Benji_X80): для использования SF3 $form->getErrors(true, false);

Tjorriemorrie
источник
3
Я знаю, что это старый ответ, но для справки в будущем: This method should only be used to help debug a form.( источник )
cheesemacfly
getErrorsAsString () не рекомендуется в версии 3.0, используйте: $ form-> getErrors (true, false);
Benji_X80
15

Функция для Symfony 2.1 и новее, без устаревшей функции:

/**
 * @param \Symfony\Component\Form\Form $form
 *
 * @return array
 */
private function getErrorMessages(\Symfony\Component\Form\Form $form)
{
    $errors = array();

    if ($form->count() > 0) {
        foreach ($form->all() as $child) {
            /**
             * @var \Symfony\Component\Form\Form $child
             */
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    } else {
        /**
         * @var \Symfony\Component\Form\FormError $error
         */
        foreach ($form->getErrors() as $key => $error) {
            $errors[] = $error->getMessage();
        }
    }

    return $errors;
}
stwe
источник
Я собирался опубликовать новый ответ на этот пост, но, похоже, вы меня опередили. Мне пришлось просмотреть исходный код, чтобы понять, почему не были найдены вызовы методов.
Доктор Ноуиталл
Я заметил, что это не приводит к ошибкам из элементов, для которых для пузырей ошибок установлено значение true. SF2.4
kinghfb
@stwe какова цель первого IFутверждения? Почему это взаимоисключающие? Насколько я понимаю: у формы могут быть как собственные ошибки, так и дочерние.
Слава Фомин II
4

Переведенные сообщения об ошибках формы (Symfony2.1)

Я много пытался найти эту информацию, поэтому я думаю, что определенно стоит добавить примечание о переводе ошибок формы.

@Icode4foodответ вернет все ошибки формы. Однако возвращаемый массив не принимает во внимание плюрализацию сообщения или перевод. .

Вы можете изменить цикл @Icode4foodответа foreach, чтобы получить комбо:

  • Получить все ошибки определенной формы
  • Вернуть переведенную ошибку
  • При необходимости учтите множественное число

Вот:

foreach ($form->getErrors() as $key => $error) {

   //If the message requires pluralization
    if($error->getMessagePluralization() !== null) {
        $errors[] = $this->container->get('translator')->transChoice(
            $error->getMessage(), 
            $error->getMessagePluralization(), 
            $error->getMessageParameters(), 
            'validators'
            );
    } 
    //Otherwise, we do a classic translation
    else {
        $errors[] = $this->container->get('translator')->trans(
            $error->getMessage(), 
            array(), 
            'validators'
            );
    }
}

Этот ответ был составлен из 3 разных сообщений:

Мик
источник
Просто попробовал вашу версию и все прошло Fatal Error: Call to undefined method Symfony\Component\Form\FormError::getMessagePluralization(). Я подозреваю, что это только для Symfony 2.1?
Царь Пино
4

SYMFONY 3.X

Другие методы SF 3.X, приведенные здесь, у меня не работали, потому что я мог отправлять в форму пустые данные (но у меня есть ограничения NotNull / NotBlanck). В этом случае строка ошибки будет выглядеть так:

string(282) "ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be null.
name:
    ERROR: This value should not be blank.
"

Что не очень полезно. Итак, я сделал это:

public function buildErrorArray(FormInterface $form)
{
    $errors = [];

    foreach ($form->all() as $child) {
        $errors = array_merge(
            $errors,
            $this->buildErrorArray($child)
        );
    }

    foreach ($form->getErrors() as $error) {
        $errors[$error->getCause()->getPropertyPath()] = $error->getMessage();
    }

    return $errors;
}

Что вернет это:

array(7) {
  ["data.name"]=>
  string(31) "This value should not be blank."
  ["data.street"]=>
  string(31) "This value should not be blank."
  ["data.zipCode"]=>
  string(31) "This value should not be blank."
  ["data.city"]=>
  string(31) "This value should not be blank."
  ["data.state"]=>
  string(31) "This value should not be blank."
  ["data.countryCode"]=>
  string(31) "This value should not be blank."
  ["data.organization"]=>
  string(30) "This value should not be null."
}
сбуба
источник
3

Вы также можете использовать службу валидатора, чтобы получить нарушения ограничений:

$errors = $this->get('validator')->validate($user);
антуан
источник
6
Это подтвердит объект, но не форму. Если, например, причиной ошибки был токен CRSF, сообщение не будет включено.
Icode4food
3

Переведенные сообщения об ошибках формы (Symfony2.3)

Мой вариант решения проблемы:

/src/Acme/MyBundle/Resources/config/services.yml

services:
    form_errors:
        class: Acme\MyBundle\Form\FormErrors

/src/Acme/MyBundle/Form/FormErrors.php

<?php
namespace Acme\MyBundle\Form;

class FormErrors
{
    public function getArray(\Symfony\Component\Form\Form $form)
    {
        return $this->getErrors($form);
    }

    private function getErrors($form)
    {
        $errors = array();

        if ($form instanceof \Symfony\Component\Form\Form) {

            // соберем ошибки элемента
            foreach ($form->getErrors() as $error) {

                $errors[] = $error->getMessage();
            }

            // пробежимся под дочерним элементам
            foreach ($form->all() as $key => $child) {
                /** @var $child \Symfony\Component\Form\Form */
                if ($err = $this->getErrors($child)) {
                    $errors[$key] = $err;
                }
            }
        }

        return $errors;
    }
}

/src/Acme/MyBundle/Controller/DefaultController.php

$form = $this->createFormBuilder($entity)->getForm();
$form_errors = $this->get('form_errors')->getArray($form);
return new JsonResponse($form_errors);

В Symfony 2.5 вы можете легко получить все ошибки полей:

    $errors = array();
    foreach ($form as $fieldName => $formField) {
        foreach ($formField->getErrors(true) as $error) {
            $errors[$fieldName] = $error->getMessage();
        }
    }
Lebnik
источник
3

Для Symfony 3.2 и выше используйте это,

public function buildErrorArray(FormInterface $form)
{
    $errors = array();

    foreach ($form->getErrors() as $key => $error) {
        if ($form->isRoot()) {
            $errors['#'][] = $error->getMessage();
        } else {
            $errors[] = $error->getMessage();
        }
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = (string) $child->getErrors(true, false);
        }
    }
    return $errors;
}

Используйте str_replace, если хотите избавиться от надоедливого текста « Ошибка: » в каждом тексте описания ошибки.

$errors[$child->getName()] = str_replace('ERROR:', '', (string) $child->getErrors(true, false));
Анджана Сильва
источник
2

Если вы используете собственные валидаторы, Symfony не возвращает ошибки, сгенерированные этими валидаторами в $form->getErrors(). $form->getErrorsAsString()вернет все необходимые ошибки, но, к сожалению, его вывод отформатирован как строка, а не как массив.

Метод, который вы используете для получения всех ошибок (независимо от их происхождения), зависит от того, какую версию Symfony вы используете.

Большинство предлагаемых решений включают создание рекурсивной функции, которая просматривает все дочерние формы и извлекает соответствующие ошибки в один массив. В Symfony 2.3 этой $form->hasChildren()функции нет, но она есть $form->all().

Вот вспомогательный класс для Symfony 2.3, который вы можете использовать для извлечения всех ошибок из любой формы. (Он основан на коде из комментария yapro к сообщению об ошибке в аккаунте Symfony на github.)

namespace MyApp\FormBundle\Helpers;

use Symfony\Component\Form\Form;

class FormErrorHelper
{
    /**
     * Work-around for bug where Symfony (2.3) does not return errors from custom validaters,
     * when you call $form->getErrors().
     * Based on code submitted in a comment here by yapro:
     * https://github.com/symfony/symfony/issues/7205
     *
     * @param Form $form
     * @return array Associative array of all errors
     */
    public function getFormErrors($form)
    {
        $errors = array();

        if ($form instanceof Form) {
            foreach ($form->getErrors() as $error) {
                $errors[] = $error->getMessage();
            }

            foreach ($form->all() as $key => $child) {
                /** @var $child Form */
                if ($err = $this->getFormErrors($child)) {
                    $errors[$key] = $err;
                }
            }
        }

        return $errors;
    }
}

Телефонный код:

namespace MyApp\ABCBundle\Controller;

use MyApp\FormBundle\Helpers;

class MyController extends Controller
{
    public function XYZAction()
    {
        // Create form.

        if (!$form->isValid()) {
            $formErrorHelper = new FormErrorHelper();
            $formErrors = $formErrorHelper->getFormErrors($form);

            // Set error array into twig template here.
        }
    }

}
Джей Шет
источник
2

Основываясь на ответе @Jay Seth, я сделал версию класса FormErrors специально для Ajax Forms:

// src/AppBundle/Form/FormErrors.php
namespace AppBundle\Form;

class FormErrors
{

    /**
     * @param \Symfony\Component\Form\Form $form
     *
     * @return array $errors
     */
    public function getArray(\Symfony\Component\Form\Form $form)
    {
        return $this->getErrors($form, $form->getName());
    }

    /**
     * @param \Symfony\Component\Form\Form $baseForm
     * @param \Symfony\Component\Form\Form $baseFormName
     *
     * @return array $errors
     */
    private function getErrors($baseForm, $baseFormName) {
        $errors = array();
        if ($baseForm instanceof \Symfony\Component\Form\Form) {
            foreach($baseForm->getErrors() as $error) {
                $errors[] = array(
                    "mess"      => $error->getMessage(),
                    "key"       => $baseFormName
                );
            }

            foreach ($baseForm->all() as $key => $child) {
                if(($child instanceof \Symfony\Component\Form\Form)) {
                    $cErrors = $this->getErrors($child, $baseFormName . "_" . $child->getName());
                    $errors = array_merge($errors, $cErrors);
                }
            }
        }
        return $errors;
    }
}

Использование (например, в вашем действии):

$errors = $this->get('form_errors')->getArray($form);

Версия Symfony: 2.8.4

Пример ответа JSON:

{
    "success": false,
    "errors": [{
        "mess": "error_message",
        "key": "RegistrationForm_user_firstname"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_lastname"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_email"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_zipCode"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_password_password"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_terms"
    }, {
        "mess": "error_message2",
        "key": "RegistrationForm_terms"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_marketing"
    }, {
        "mess": "error_message2",
        "key": "RegistrationForm_marketing"
    }]
}

Объект ошибки содержит «ключевое» поле, которое является идентификатором входного элемента DOM, поэтому вы можете легко заполнить сообщения об ошибках.

Если у вас есть дочерние формы внутри родительской, не забудьте добавить cascade_validationпараметр внутри родительской формы setDefaults.

RobbeR
источник
1

Для Symfony 2.1 и более поздних версий для использования с отображением ошибок Twig я изменил функцию, чтобы добавить FormError вместо простого их извлечения, таким образом у вас будет больше контроля над ошибками и вам не нужно использовать error_bubbling для каждого отдельного ввода. Если вы не установите его указанным ниже способом, {{form_errors (form)}} останется пустым:

/**
 * @param \Symfony\Component\Form\Form $form
 *
 * @return void
 */
private function setErrorMessages(\Symfony\Component\Form\Form $form) {      

    if ($form->count() > 0) {
        foreach ($form->all() as $child) {
            if (!$child->isValid()) {
                if( isset($this->getErrorMessages($child)[0]) ) {
                    $error = new FormError( $this->getErrorMessages($child)[0] );
                    $form->addError($error);
                }
            }
        }
    }

}
Страна чудес вкрутую
источник
1

Я придумал это решение. Он отлично работает с последней версией Symfony 2.4 .

Я постараюсь дать некоторые пояснения.

Использование отдельного валидатора

Я считаю плохой идеей использовать отдельную проверку для проверки сущностей и возврата сообщений о нарушении ограничений, как это предлагают другие авторы.

  1. Вам нужно будет вручную проверить все сущности, указать группы проверки и т. Д. И т. Д. Со сложными иерархическими формами это вообще непрактично и быстро выйдет из-под контроля.

  2. Таким образом, вы будете проверять форму дважды: один раз с формой и один раз с отдельным валидатором. Это плохая идея с точки зрения производительности.

Я предлагаю рекурсивно перебирать тип формы с его дочерними элементами для сбора сообщений об ошибках.

Использование некоторых предложенных методов с эксклюзивным оператором IF

Некоторые ответы, предложенные другими авторами, содержат взаимоисключающие операторы IF, например: if ($form->count() > 0)или if ($form->hasChildren()).

Насколько я понимаю, в любой форме могут быть не только дочерние элементы, но и ошибки. Я не разбираюсь в компоненте Symfony Forms , но на практике вы не получите некоторых ошибок самой формы, таких как ошибка защиты CSRF или дополнительные поля. . Предлагаю убрать это разделение.

Использование денормализованной структуры результатов

Некоторые авторы предлагают помещать все ошибки в простой массив. Таким образом, все сообщения об ошибках самой формы и ее дочерних элементов будут добавлены в один и тот же массив с разными стратегиями индексации: на основе чисел для собственных ошибок типа и на основе имен для ошибок дочерних элементов. Предлагаю использовать нормализованную структуру данных вида:

errors:
    - "Self error"
    - "Another self error"

children
    - "some_child":
        errors:
            - "Children error"
            - "Another children error"

        children
            - "deeper_child":
                errors:
                    - "Children error"
                    - "Another children error"

    - "another_child":
        errors:
            - "Children error"
            - "Another children error"

Таким образом, результат можно будет легко повторить позже.

Мое решение

Итак, вот мое решение этой проблемы:

use Symfony\Component\Form\Form;

/**
 * @param Form $form
 * @return array
 */
protected function getFormErrors(Form $form)
{
    $result = [];

    // No need for further processing if form is valid.
    if ($form->isValid()) {
        return $result;
    }

    // Looking for own errors.
    $errors = $form->getErrors();
    if (count($errors)) {
        $result['errors'] = [];
        foreach ($errors as $error) {
            $result['errors'][] = $error->getMessage();
        }
    }

    // Looking for invalid children and collecting errors recursively.
    if ($form->count()) {
        $childErrors = [];
        foreach ($form->all() as $child) {
            if (!$child->isValid()) {
                $childErrors[$child->getName()] = $this->getFormErrors($child);
            }
        }
        if (count($childErrors)) {
            $result['children'] = $childErrors;
        }
    }

    return $result;
}

Надеюсь, это кому-то поможет.

Слава Фомин II
источник
@weaverryan, пожалуйста, взгляните на мое решение? Это действительно так, или есть недостатки или какие-то заблуждения? Спасибо!
Слава Фомин II
1

СИМФОНИЯ 3.1

Я просто реализовал статический метод для обработки отображения ошибок

static function serializeFormErrors(Form\Form $form)
{
    $errors = array();
    /**
     * @var  $key
     * @var Form\Form $child
     */
    foreach ($form->all() as $key => $child) {
        if (!$child->isValid()) {
            foreach ($child->getErrors() as $error) {
                $errors[$key] = $error->getMessage();
            }
        }
    }

    return $errors;
}

Надеюсь помочь

Шигян Лю
источник
1

Symfony 3 и новее

Недавно я создал функцию, которая создает дерево ошибок формы. Это будет полезно для возврата списка ошибок во внешний интерфейс. Это основано на типах форм, имеющих:

'error_bubbling' => false

Код:

public static function getFormErrorsTree(FormInterface $form): array
{
    $errors = [];

    if (count($form->getErrors()) > 0) {
        foreach ($form->getErrors() as $error) {
            $errors[] = $error->getMessage();
        }
    } else {
        foreach ($form->all() as $child) {
            $childTree = self::getFormErrorsTree($child);

            if (count($childTree) > 0) {
                $errors[$child->getName()] = $childTree;
            }
        }
    }

    return $errors;
}

Вывод:

Array
(
    [name] => Array
        (
            [0] => This value is not valid.
        )

    [emails] => Array
        (
            [0] => Array
                (
                    [0] => Given e-mail is not valid.
                    [1] => Given e-mail is not valid #2.
                )
            [1] => Array
                (
                    [0] => Given e-mail is not valid.
                    [1] => Given e-mail is not valid #2.
                )

        )

)

Примечание : я знаю, что ошибки из полей более глубокого уровня могут быть перезаписаны, если на более высоком уровне есть ошибки, но это сделано специально для моего использования.

Кшиштоф Трзос
источник
0

Для Symfony 2.1:

Это мое окончательное решение, объединяющее многие другие решения:

protected function getAllFormErrorMessages($form)
{
    $retval = array();
    foreach ($form->getErrors() as $key => $error) {
        if($error->getMessagePluralization() !== null) {
            $retval['message'] = $this->get('translator')->transChoice(
                $error->getMessage(), 
                $error->getMessagePluralization(), 
                $error->getMessageParameters(), 
                'validators'
            );
        } else {
            $retval['message'] = $this->get('translator')->trans($error->getMessage(), array(), 'validators');
        }
    }
    foreach ($form->all() as $name => $child) {
        $errors = $this->getAllFormErrorMessages($child);
        if (!empty($errors)) {
           $retval[$name] = $errors; 
        }
    }
    return $retval;
}
Фернандо П.Г.
источник