Reglas de validación condicionales en Laravel

Validar formularios con Laravel es genial, nos alivia mucho el trabajo y más aún si implementamos la validación como servicio. Pero la semana pasada en la aplicación que estoy desarrollando me encontré con un pequeño ‘pero‘ respecto a las reglas de validación: necesitaba validar un campo si y sólo si otro campo del formulario contenía un valor superior a 2.

Una forma de poder solucionar el problema era crear una regla de validación customizada para la ocasión, pero no quería hacer una solución tan específica. Con el afán de no estar inventando la rueda busqué en Google si existía algo que me permitiera hacer esto en Laravel, encontrándome con una regla de validación if..else en el foro oficial de la comunidad. De igual forma era una regla customizada, pero no con el enfoque que yo había pensado. Permitía hacer algo como esto:

'campo' => 'if_else:(otro_campo=1),required+numeric,numeric+max:10';

Entonces, eso se traduce a lo siguiente: las reglas de validación de campo dependen de la condición otro_campo=1. Por lo que si otro_campo es igual a 1, las reglas a ejecutar son required y numeric, de lo contrario las reglas son numericmax:10.

La solución funcionaba – luego de arreglar ciertos errores -, pero sabía que no era óptima y lamentablemente no tenía, ni tengo hasta el momento, el tiempo de crear una solución mejor. Teniendo en cuenta mi caso – el cual me hizo llegar a la búsqueda de todo esto -, pensé que este tipo de validaciones condicionales debían ser soportadas nativamente por Laravel. Mi aplicación es simple y estática, y si yo me encontré con ese tipo de problemas, me imagino que en una aplicación más compleja y dinámica de seguro aparecen situaciones como ésta.

Con ese afán creé en GitHub un issue la semana pasada comentando mi situación, la solución que encontré y que sería genial si Laravel pudiera implementar este tipo de validaciones por así decirlo dinámicas. La grata noticia para mi y para toda la comunidad, es que Taylor Otwell finalmente implementó en Laravel las validaciones condicionales, siendo soportadas nativamente por el framework – esto hace menos de dos horas atrás de estar publicando esto -.

Entonces, ¿cómo funciona esto?. Vamos a tomar el ejemplo que está en la documentación – que es una variación al ejemplo que puse en GitHub – en el cual se toma el caso de una aplicación web para coleccionistas de videojuegos. Si un coleccionista se registra y tiene 100 videojuegos o más, queremos que nos explique porque tiene tantos videojuegos, quizás tienen una tienda o simplemente les gusta coleccionar. En primer lugar debemos tener el validador con las reglas estáticas, las cuales nunca cambian:

$v = Validator::make($data, array(
    'email' => 'required|email',
    'games' => 'required|numeric',
));

Bien, ahora debemos validar de manera condicional el campo donde el usuario entrega el motivo por el cual tiene tantos videojuegos – sólo si tiene 100 o más -. Es aquí donde utilizamos el método sometimes del objeto Validator, ¡la chica nueva!:

$v->sometimes('reason', 'required|max:500', function($input)
{
    return $input->games >= 100;
});

El primer parámetro es el campo que queremos validar de manera condicional, en este caso reason. En segundo lugar tenemos las reglas para validar ese campo. Por último tenemos un Closure que debe retornar true o false. Si el Closure devuelve true las reglas son agregadas al campo reason, si por el contrario retorna false el campo no es validado. El campo $input que es pasado al Closure es una instancia de Illuminate\Support\Fluent y pueden acceder a todos los datos enviados desde el formulario como si fuese un objeto, es así como dentro del Closure tenemos la condición $input->games >= 100 haciendo referencia al campo games del formulario.

También pueden aplicar una condición a más de un campo a la vez:

$v->sometimes(array('reason', 'cost'), 'required', function($input)
{
    return $input->games >= 100;
});

De ese modo si el usuario ingresa 100 o más videojuegos los campos reason y cost se vuelven requeridos.

Espero haya sido de utilidad ;)

NOTA: Si estás leyendo esto cercano a la fecha de publicación de esta entrada (03/10/2013) y no haz hecho composer update hace buen tiempo, deberás hacerlo para poder tener esta característica integrada a Laravel y poder utilizarla.

Anuncios

Deja un comentario (puedes utilizar Markdown)

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s