Jueves, agosto 8, 2019

Validación de una colección de formularios incrustados en Symfony 4.3

La opción de incrustar una colección de formularios en otro es útil para implementar interfaces ricas y bien estructuradas. Sin embargo, la documentación no toca todos los detalles que se debe considerar, en particular lo relativo a la validación de los datos.

Vamos a asumir que ya leíste los documentos oficiales, y por lo tanto has implementado todo esto:

  1. Una entidad "cabecera" y otra "detalle", relacionadas 1 a N, con sus respectivas reglas de validación.
  2. Clases de formulario (type) para cada una, con la segunda incrustada mediante una colección (CollectionType) en la primera.
  3. Plantillas twig y el código JS necesario para agregar y eliminar elementos de la colección.
  4. Un controlador que coordina las operaciones.

Teniendo en cuenta que todo esto puede haberte tomado bastante trabajo, encontrarás bastante decepcionante que las validaciones asociadas a la entidad "detalle" no sean ejecutadas. Sin importar cuánto te hayas esmerado en escribir las reglas, ellas serán ignoradas porque a la documentación le falta mencionar unos cuantos detalles.

La cascada que ya no va

En primer lugar, debes indicar explícitamente que deseas ejecutar las reglas de validación de la entidad "detalle". Hasta Symfony 3, ello se conseguía mediante la opción cascade_validation; en la actualidad, debes declarar una constraint Valid() en las opciones de la colección. La declaración debería incluir lo siguiente:

use Symfony\Component\Form\Extension\Core\Type as Core;
use Symfony\Component\Validator\Constraints as Assert;
[...]
            ->add('xxx', Core\CollectionType::class, [
                [...]
                'constraints' => [
                    new Assert\Valid(),
                    new Assert\Count([ 'min' => 1 ]),
                ],
                [...]

Adicionalmente, si la colección debe satisfacer otras condiciones, como un número mínimo o máximo de elementos, puedes aprovechar de incluir la constraint Count() u otras.

¿Y dónde está el error?

Aunque el código de validación ahora esté ejecutándose, es posible que los errores no aparezcan en el formulario. Puedes confirmar que este sea el caso al observar que:

  1. El formulario no se procesa (porque ->isValid() r
  2. etorna false).
  3. No se muestra errores al usuario.
  4. Los errores efectivamente aparecen en el web debug toolbar.

La solución es agregar las llamadas a form_errors() que pueda faltar en la plantilla; tanto la asociada al formulario "cabecera", como la correspondiente al "detalle". Esto último es particulamente relevante si has personalizado el despliegue del segundo. ✦

También podría interesarte

La tripulante

La Tierra agoniza, y solo unos pocos gozan del privilegio de vivir en lugares protegidos como Ciudad Cisne. Culpándose por el error que impidió a sus amigos emigrar a una colonia extrasolar, el otrora brillante ingeniero aeroespacial Leandro Huerta acepta que no logrará reencauzar su carrera sino hasta resolver la enigmática muerte de su madre, quien lo excluyó de su vida años atrás, en respuesta a su elección profesional.

Juan Cataldo

Reparamos astronaves

El progreso es inevitable, y no espera a los que se quedan atrás.

Ciencia ficción

Afinidad

¿Qué tan difícil podía ser transportar a la delegación diplomática de Eros?

Ciencia ficción