Я придумал это решение. Он отлично работает с последней версией Symfony 2.4 .
Я постараюсь дать некоторые пояснения.
Использование отдельного валидатора
Я считаю плохой идеей использовать отдельную проверку для проверки сущностей и возврата сообщений о нарушении ограничений, как это предлагают другие авторы.
Вам нужно будет вручную проверить все сущности, указать группы проверки и т. Д. И т. Д. Со сложными иерархическими формами это вообще непрактично и быстро выйдет из-под контроля.
Таким образом, вы будете проверять форму дважды: один раз с формой и один раз с отдельным валидатором. Это плохая идея с точки зрения производительности.
Я предлагаю рекурсивно перебирать тип формы с его дочерними элементами для сбора сообщений об ошибках.
Использование некоторых предложенных методов с эксклюзивным оператором 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;
}
Надеюсь, это кому-то поможет.