Los formularios de Symfony 1.4

2.6. Validadores globales

Los validadores mostrados hasta el momento siempre están asociados a un campo específico del formulario y sólo permite validar un valor. Además, estos validadores son independientes del resto de información enviada por el usuario. No obstante, en ocasiones la validación de un campo depende del contexto o depende del valor de muchos otros campos. Los ejemplos típicos de validadores globales son los dos campos de contraseña que deben ser iguales o el campo de fecha de inicio que debe ser anterior que la fecha de finalización.

En cualquiera de estos casos, se debe utilizar un validador global que valide los datos introducidos teniendo en cuenta su contexto. Los validadores globales se pueden establecer antes o después de la validación individual de los campos mediante los pre-validadores y los post-validadores respectivamente. Normalmente es mejor utilizar un post-validador porque así los datos ya están validados y limpios, por lo que su formato también se ha normalizado. El listado 2-13 muestra cómo comparar el valor de dos contraseñas mediante el validador sfValidatorSchemaCompare.

Listado 2-13 - Utilizando el validador sfValidatorSchemaCompare

$this->validatorSchema->setPostValidator(new sfValidatorSchemaCompare('password1', sfValidatorSchemaCompare::EQUAL, 'password2'));

A partir de Symfony 1.2, también puedes utilizar los operadores habituales de PHP para realizar las comparaciones en vez de las constantes de la clase sfValidatorSchemaCompare. Por tanto, el ejemplo anterior es equivalente a:

$this->validatorSchema->setPostValidator(new sfValidatorSchemaCompare('password1', '==', 'password2'));

Nota Al igual que el resto de validadores globales, la clase sfValidatorSchemaCompare hereda del validador sfValidatorSchema. De hecho, el propio sfValidatorSchema es un validador global, ya que valida todos los datos introducidos por el usuario pasando el valor de cada campo a su validador asociado.

El listado 2-14 muestra cómo emplear un único validador para validar que una fecha de inicio sea anterior a la fecha de finalización y además añade un mensaje de error personalizado.

Listado 2-14 - Utilizando el validador sfValidatorSchemaCompare

$this->validatorSchema->setPostValidator(
  new sfValidatorSchemaCompare('fecha_inicio', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'fecha_fin',
    array(),
    array('invalid' => 'La fecha de inicio ("%left_field%") debe ser anterior a la fecha de finalización ("%right_field%")')
  )
);

Utilizar un post-validador asegura que la comparación entre las dos fechas es precisa. Independientemente del formato en el que se introduce cada fecha, la validación de los campos fecha_inicio y fecha_fin asegura que sus valores se convierten en un formato fácilmente comparable (Y-m-d H:i:s por defecto).

Por defecto, los pre-validadores y los post-validadores devuelven errores de tipo global al formulario. No obstante, algunos de esos validadores pueden asociar un error a un campo determinado. La opción throw_global_error por ejemplo del validador sfValidatorSchemaCompare permite elegir entre un error global (figura 2-10) y un error asociado al primer campo (figura 2-11). El listado 2-15 muestra cómo utilizar la opción throw_global_error.

Listado 2-15 - Utilizando la opción throw_global_error

$this->validatorSchema->setPostValidator(
  new sfValidatorSchemaCompare('fecha_inicio', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'fecha_fin',
    array('throw_global_error' => true),
    array('invalid' => 'La fecha de inicio ("%left_field%")  debe ser anterior a la fecha de finalización ("%right_field%")')
  )
);
Error global de un validador global

Figura 2.10 Error global de un validador global

Error local de un validador global

Figura 2.11 Error local de un validador global

Por último, si se utiliza un validador lógico es posible combinar varios post-validadores como muestra el listado 2-16.

Listado 2-16 - Combinando varios post-validadores mediante un validador lógico

$this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
  new sfValidatorSchemaCompare('fecha_inicio', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'fecha_fin'),
  new sfValidatorSchemaCompare('password1', sfValidatorSchemaCompare::EQUAL, 'password2'),
)));