Obtenga todos los errores junto con los campos a los que está conectado el error

Estoy utilizando formularios Symfony2 para validar solicitudes POST y PUT a una API. El formulario maneja el enlace de los datos de solicitud a la entidad subyacente y luego valida la entidad. Todo funciona bastante bien, excepto por la recostackción de errores. Estoy usando FOSRestBundle y estoy lanzando un Symfony \ Component \ HttpKernel \ Exception \ HttpException con un código de estado 400 y un mensaje que contiene los mensajes de error de formulario si la validación falla. El FOSRestBundle se encarga de convertir esto en una respuesta JSON. El método del controlador que tengo que realizar es similar al siguiente (todos los campos muestran sus errores hasta el formulario):

protected function validateEntity(AbstractType $type, $entity, Request $request) { $form = $this->createForm($type, $entity); $form->bind($request); if (! $form->isValid()) { $message = ['Invalid parameters passed.']; foreach ($form->getErrors() as $error) { $message[] = $error->getMessage(); } throw new HttpException(Codes::HTTP_BAD_REQUEST, implode("\n", $message)); } } 

El problema que tengo es que cuando recopilo los errores de nivel de formulario a través de $ form-> getErrors () solo puedo acceder al mensaje de error y no al nombre del campo al que está conectado el error. Este es un problema particular cuando un parámetro POST o PUT corresponde a un id para una entidad relacionada. Si se envía un valor no válido, los mensajes de error son simplemente ‘Este valor no es válido’, que no es muy bueno en este contexto. Idealmente, me gustaría hacer cualquiera de los siguientes:

  • Para cada error obtenga el nombre del campo al que está conectado para que pueda formatear el mensaje algo así como “nombre de campo: mensaje de error”
  • Si eso no es posible, ¿es posible personalizar el mensaje de error para un tipo de entidad no válida para que se muestre algo mejor que “Este valor no es válido”?

Puede tomar el método getErrorsAsString como ejemplo para obtener la funcionalidad que desea. También debe establecer la opción invalid_message en el campo de formulario para cambiar This value is invalid mensaje This value is invalid .

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

Use esta función para obtener todos los mensajes de error después del formulario de enlace.

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

Creé un paquete para ayudar con este problema.

Puedes obtenerlo aqui:

https://github.com/Ex3v/FormErrorsBundle

Las contribuciones son bienvenidas. Aclamaciones.

Necesitaba una solución para obtener una matriz asociativa de todos los errores de todos los formularios nesteds con la clave formateada, de modo que representa la identificación del documento del elemento del campo de formulario correspondiente:

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