Esta nueva característica de Laravel 5 llamada Form Requests reemplaza la validación y la autorización para dar facilidad y potencia a la cara oculta de los formularios.
Antiguamente dependíamos de la clase Validation
que podíamos utilizarla en distintas partes como controladores, modelos o servicios, pero siempre teníamos la duda de cual era el mejor sitio para validar los datos que llegan a través de los formularios. Ahora esto queda resuelto con los Form Requests.
Clases Form y HTML
Lo primero que tenemos que tener en cuenta es que las clases Form
y HTML
ya no se encuentran en Laravel 5 y debemos habilitarlas mediante un paquete externo llamado illuminate/html.
Así que para utilizar estos helpers en nuestras vistas (como por ejemplo Form::open
o Form::text
), debemos incluir el paquete dentro de nuestro composer.json
y ejecutar composer update
:
"require":
,
Tras instalar el paquete necesitamos referenciar las clases en los arrays de proveedores y alias. Editamos el fichero config/app.php
y añadimos lo siguiente:
'providers' => [
// ...
'Illuminate\Html\HtmlServiceProvider',
],
'aliases' => [
// ...
'Form' => 'Illuminate\Html\FormFacade',
'HTML' => 'Illuminate\Html\HtmlFacade'
],
Form Requests
Cuando un formulario envía datos a nuestra aplicación ahora podremos validar y/o autorizar mediante la nueva clase Illuminate\Http\Request
.
Creamos un fichero de ejemplo mediante el nuevo comando php artisan make:request PostFormRequest
, lo que da como resultado lo siguiente:
;
;
Validación
El tema de la validación corre a cargo de rules()
, que funciona igual que en versiones anteriores (clase Validation
) solo que ahora tendremos todas las reglas organizadas en ficheros separados. Por ejemplo, podemos crear este set de reglas:
{
return [
'post_name' => 'required',
'author_email' => 'required|email'
];
}
La potencia reside en la extensibilidad. Podemos por ejemplo, crear un set de reglas básico en PostFormRequest.php
y después extender dicha clase con otro set de reglas a través de otros ficheros como AddPostFormRequest.php
o EditPostFormRequest.php
.
Autorización
El tema de la autorización es muy sencillo. Si la función authorize()
devuelve false
, el usuario no tendrá acceso al controlador y será devuelto al formulario indicando un error (podemos modificar este comportamiento).
Es en esta función donde insertaremos nuestra lógica condicional para determinar si el usuario tiene acceso (true
) o no (false
).
Uso
Para utilizar nuestra clase de tipo Request
en los controladores basta con añadir use App/Http/Requests/PostFormRequest;
al principio de nuestro controlador y después injectar la clase a nuestros métodos, tal que así:
;
;
;
De esta manera las peticiones POST que provengan de formularios pasarán primero por la validación y la autorización de la clase PostFormRequest
y si uno de los dos son rechazados, la petición nunca llegará a ejecutar el código de nuestro controlador.
Otros
Dentro de la clase de tipo Request
podemos sobreescribir algunas funciones y variables para alterar el comportamiento por defecto.
Funciones
En el caso de las funciones tenemos forbiddenResponse()
y response()
.
La función forbiddenResponse()
se encarga de generar una respuesta cuando la autorización falla. Por defecto genera un error 403 pero como decimos, podemos cambiar su comportamiento. Ejemplo:
{
return $this->redirector;
}
En el caso de response()
, podemos ver lo que ocurre por defecto aquí y alterar su comportamiento cuando la validación de nuestras reglas falla.
Variables
En cuanto a las variables, podemos alterar las siguientes:
// La URI a la que redireccionará si falla la validación
protected $redirect;
// La ruta a la que redireccionará si falla la validación
protected $redirectRoute;
// La acción a la que redireccionará si falla la validación
protected $redirectAction;
// Los datos que no serán enviados de vuelta en la redirección por seguridad
protected $dontFlash = ['password', 'password_confirmation'];
La prioridad de las redirecciones es la indicada arriba y si no damos uso a esas variables simplemente se hará un return $url->previous();
.