Ultima Laravel
Share
Explore

icon picker
Validación

La validación es una cuestión fundamental en cualquier aplicación, no sólo web. Cualquiera.
Validar consiste en verificar la validez de los datos antes de procesarlos.
¿Validar en cliente o en servidor?.
En el cliente es más rápido, no necesitamos conectar con el servidor ni hacer uso de la red.
Pero nunca debemos confiar en la validación realizada en el cliente. Puede ser burlada intencionadamente o anulada de forma involuntaria.
Validar en el cliente es opcional pero en el servidor es obligatorio.

Cómo validar en Laravel

Existen varias maneras de hacerlo.
Nosotros usaremos el método validate del objeto $request.
Ejemplo:
public function store(Request $request)
{
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
//validado -> a guardar
}

¿¿Qué pasa tras la validación ??

Si la validación falla se produce una excepción y se reenvía la petición a la URL previa.
Se crea un objeto $errors que permite mostrar los errores de validación.
Los datos del formulario se flashean a la sesión y estarán disponibles sólo en la próxima peticicón para ser volver a rellenar el formulario como estaba.
OJO. Si usamos Ajax se envía una respuesta al cliente con un código 422 y un JSON con los mensajes de error.

Rellenando con los datos viejos

La función helper old() nos permite acceder a los datos que no se han validado y están en la sesión.
<label>Nombre:</label>
<input type="text" name="name" value="{{ old('name')}}">

Mostrando los errores con blade

Todos los errores de la página
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
Mostrar los errores de un campo:
//sólo el primero
{{ $errors->first('name') }}

//o todos los del campo
@foreach($errors->get('name') as $error)
{{ $error }}
@endforeach
También podemos usar la directiva @error de blade:
<label for="title">Post Title</label>
<input id="title" type="text" class="@error('title') is-invalid @enderror">
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror

Traduciendo mensajes

Podemos traducir todos los literales de Laravel. No sólo los de validación.
Debemos acceder a la
Descargar la carpeta del idioma que nos interese.
Configurar el lenguaje en config.php

Reglas

Se pueden añadir múltiples reglas para cada campo. Entre comillas y separadas por la barra vertical.
La regla bail hace que no se sigan evaluando más reglas si esa falla.
Revisar la documentación oficial: Available Validation Rules.

Unique y update

Ojo cuando apliquemos la regla unique en actualizaciones (update).
Si aplicamos la regla sin más va a fallar porque ya existe un registro con ese dato:
'code' => 'required|unique:studies|max:6',
Debemos indicar que no tenga en cuenta el propio registro para comprobar esta regla:
'code' => 'required|max:6|unique:studies,code,' . $study->id,

Otros modos de validar

Hemos planteado la forma habitual pero existen otras:
Creando clases Request a la medida de una validación.
Creando clases Validator
Ambas soluciones son algo más sofisticadas y no las vamos a usar aunque podrían dar solución a situaciones más complejas.

Autorización: reglas y políticas

Laravel nos brinda dos sistemas para autorizar acciones: reglas y puertas.
Reglas
Las reglas se definen asociadas a la clase Gate.
Son una solución más simple.
Políticas
Son soluciones más elaboradas que engloban la autorización referida a un modelo concreto.
Se definen en clases dentro guardadas en app/Policies
Tienen una analogía a rutas y controladores, simplicidad vs complejidad y orden.
En un proyecto usaremos una u otra (o ambas) de acuerdo a su complejidad y envergadura.

Definir reglas

Las reglas se definen en el AuthServiceProvider.php, dentro de su función boot.
Podemos definir una regla con un closure (función anónima) dentro de dicho método:
public function boot()
{
$this->registerPolicies();
//nuestra regla es esta:
Gate::define('update-post', function ($user, $post) {
return $user->id == $post->user_id;
});
}

Usar reglas

Para comprobar las reglas debemos usar la fachada Gate y alguno de sus métodos (allows, denies). Lo podemos hacer en la propia ruta o más correctamente en el controlador o en un middleware:
if (Gate::denies('update-post', $post)) {
abort(403);
//o podríamos redireccionar:
// return redirect('/home');
// o mostrar una vista
// return view('nombreVista');
}
Observa que el $user no es pasado a la clase Gate, toma el autenticado. Si quisiéramos pasarlo debemos hacerlo así:
//preguntando si se le permite
if (Gate::forUser($user)->allows('update-post', $post)) {
// The user can update the post...
}
//o al revés ...
if (Gate::forUser($user)->denies('update-post', $post)) {
// The user can't update the post...
}

Políticas

Si el proyecto es pequeño la solución anterior es válida pero para algo grande puede no ser una buena solución.
Las políticas separan código para no sobrecargar el código del AuthServiceProvider.
Las políticas son clases guardadas en app/Policies y que se crean así:
//clase en blanco
php artisan make:policy PostPolicy

//clase con reglas CRUD predefinidas asociada a un modelo
//recomendable:

php artisan make:policy PostPolicy --model=Post

Tras crear las políticas, éstas deben ser regitradas en el AuthServiceProvider:
class AuthServiceProvider extends ServiceProvider
{
//deben incluírsee en el siguiiente array:
protected $policies = [
Post::class => PostPolicy::class,
];

Escribiendo las políticas:

Podemos crear los métodos que necesitemos. Por ejemplo el método update lo podemos usar para actualizar un objeto del modelo afectado. Sus argumentos deben ser el user y un objeto del modelo protegido:
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
//aunque si el método no usa ningún objeto del modelo lo podemos dejar así:
public function create(User $user)
{
return true; //una expresión booleana...
}
El método before permite tomar decisiones generales sin evaluar la política
public function before($user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
// si devuelve true -> autorizado. No comprueba nada más
// si devuelve false -> denegado. No comprueba nada más
// si devuelve null -> lo que diga la regla usada


Share
 
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.