Symfony2: как получить ошибки проверки формы после привязки запроса к форме - PullRequest
108 голосов
/ 08 августа 2011

Вот мой 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?

Ответы [ 19 ]

116 голосов
/ 08 августа 2011

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

  • не перенаправлять пользователя при ошибке и отображать {{ form_errors(form) }} в файле шаблона
  • получить доступ к массиву ошибок как $form->getErrors()
99 голосов
/ 02 июля 2013

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)

47 голосов
/ 21 ноября 2011

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

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;
}
34 голосов
/ 14 сентября 2011

Используйте средство проверки для получения ошибок для конкретной сущности

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:

19 голосов
/ 04 февраля 2015

Чтобы получить правильные (переводимые) сообщения, в настоящее время использующие 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.

15 голосов
/ 29 марта 2013

Функция для 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;
}
15 голосов
/ 20 сентября 2012

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

Редактировать (из Benji_X80): Для SF3 используйте $form->getErrors(true, false);

4 голосов
/ 26 марта 2013

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

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

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

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

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

Здесьэто:

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 разных сообщений:

3 голосов
/ 26 ноября 2013

Перевод сообщений об ошибках формы (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);

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

    $errors = array();
    foreach ($form as $fieldName => $formField) {
        foreach ($formField->getErrors(true) as $error) {
            $errors[$fieldName] = $error->getMessage();
        }
    }
3 голосов
/ 24 августа 2011

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

$errors = $this->get('validator')->validate($user);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...