---
title: "Aprende Laravel: Validación"
excerpt: "Aprende a validar datos de entrada en Laravel: validación en el controller, Form Requests, mensajes personalizados y cómo mostrar los errores en Blade."
date: "2026-07-20T09:00:00.000Z"
category: "Laravel"
author:
  name: "angel cruz"
  picture: "https://angelcruzdevcdn.nyc3.cdn.digitaloceanspaces.com/images/me/angel-cruz.png"
ogImage:
  url: "/images/open-graph/laravel-opengraph-image.png"
seo_title: "Validación en Laravel 13: Form Requests y reglas (guía)"
seo_description: "Aprende a validar datos en Laravel 13: validación en el controller con $request->validate, Form Requests, mensajes personalizados y mostrar errores en Blade."
keywords:
  - laravel
  - validación
  - form request
  - php
  - laravel español
learning_path:
  series: "laravel-fundamentals"
  order: 7
  total: 13
  prev_slug: "aprende-laravel-proyecto-blog"
  next_slug: "aprende-laravel-autenticacion"
---

En el [proyecto del blog](/post/aprende-laravel-proyecto-blog) ya validaste datos por encima. Ahora vamos a fondo: **validar es asegurarte de que los datos que entran cumplen tus reglas antes de usarlos** (guardar en base de datos, procesar, etc.). Laravel te da dos formas principales: validar directo en el controller y, para reglas más complejas, los **Form Requests**.

## Validación en el controller

La forma más directa es el método `validate()` sobre el `$request`:

```php
public function store(Request $request): RedirectResponse
{
    $validated = $request->validate([
        'title' => ['required', 'unique:posts', 'max:255'],
        'body' => ['required'],
    ]);

    // Los datos son válidos...
    Post::create($validated);

    return redirect('/posts');
}
```

Si la validación falla, Laravel **redirige automáticamente** al formulario anterior con los errores en la sesión. No tienes que escribir ese manejo tú. Si pasa, `validate()` devuelve solo los datos validados (útil para pasarlos directo a `create()`).

## Reglas más comunes

| Regla | Qué hace |
|-------|----------|
| `required` | El campo debe estar presente y no vacío |
| `unique:posts` | El valor debe ser único en la tabla `posts` |
| `email` | Debe ser un email válido |
| `max:255` | No puede exceder 255 caracteres |
| `min:3` | Al menos 3 caracteres |
| `confirmed` | Debe tener un campo `{campo}_confirmation` que coincida |
| `nullable` | El campo puede ser nulo |
| `date` | Debe ser una fecha válida |
| `integer` | Debe ser un entero |

Las reglas se combinan en un array por campo. La lista completa está en la documentación oficial.

## Mostrar los errores en Blade

La variable `$errors` está disponible en todas las vistas automáticamente. Para mostrar todos los errores:

```blade
@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
```

Y para el error de un campo puntual, la directiva `@error`:

```blade
<label for="title">Título</label>
<input id="title" type="text" name="title" value="{{ old('title') }}"
    class="@error('title') is-invalid @enderror" />

@error('title')
    <div class="text-red-600">{{ $message }}</div>
@enderror
```

El helper `old('title')` repuebla el input con lo que el usuario había escrito, así no pierde el formulario cuando falla la validación.

## Form Requests: sacar la validación del controller

Cuando las reglas crecen, meterlas en el controller lo ensucia. Un **Form Request** es una clase dedicada a validar (y autorizar) una petición. Se genera con Artisan:

```shell
php artisan make:request StorePostRequest
```

Se crea en `app/Http/Requests` con dos métodos clave, `authorize()` y `rules()`:

```php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        // ¿Este usuario puede hacer esta petición?
        return true;
    }

    public function rules(): array
    {
        return [
            'title' => ['required', 'unique:posts', 'max:255'],
            'body' => ['required'],
            'publish_at' => ['nullable', 'date'],
        ];
    }
}
```

Luego lo **type-hinteas** en el controller y Laravel valida antes de entrar al método. Si falla, redirige solo; si pasa, ya tienes los datos validados:

```php
public function store(StorePostRequest $request): RedirectResponse
{
    // Si llegaste aquí, la petición es válida.
    $validated = $request->validated();

    // O solo una parte:
    $data = $request->safe()->only(['title', 'body']);

    Post::create($validated);

    return redirect('/posts');
}
```

El controller queda limpio: recibe datos ya validados y se concentra en su lógica.

## Mensajes y atributos personalizados

Dentro del Form Request puedes sobrescribir `messages()` y `attributes()` para textos a medida:

```php
public function messages(): array
{
    return [
        'title.required' => 'El título es obligatorio.',
        'title.unique' => 'Ya existe un post con ese título.',
    ];
}

public function attributes(): array
{
    return [
        'title' => 'título del post',
    ];
}
```

## Siguiente Paso

Ya sabes validar lo que entra. El siguiente fundamento es saber **quién** entra: cómo registrar usuarios, iniciar sesión y proteger rutas. Sigue con [Aprende Laravel: Autenticación](/post/aprende-laravel-autenticacion).

## Preguntas Frecuentes

### ¿Cuándo uso $request->validate() y cuándo un Form Request?

Usa `$request->validate()` para validaciones simples y puntuales. Pasa a un Form Request cuando las reglas crecen, se repiten entre métodos, o necesitas lógica de autorización junto con la validación.

### ¿Qué pasa si la validación falla?

Laravel redirige automáticamente a la página anterior con los mensajes de error en la sesión (la variable `$errors`) y repuebla los inputs con `old()`. No tienes que manejar la redirección a mano.

### ¿Cómo muestro el error de un solo campo?

Con la directiva `@error('campo') ... {{ $message }} ... @enderror` en Blade. La variable `$errors` también te deja recorrer todos con `$errors->all()`.

### ¿El método authorize() del Form Request es obligatorio?

Existe siempre, pero si no necesitas lógica de permisos, devuelve `true`. Si devuelve `false`, Laravel responde con un 403 antes de validar.

## Recursos Adicionales

- [Validation | Laravel 13.x](https://laravel.com/docs/13.x/validation)
- [Aprende Laravel: Controllers](/post/aprende-laravel-controllers)
- [Aprende Laravel desde cero (serie completa)](/laravel-fundamentals)

---

## Sitemap

Índice completo del sitio: [/sitemap.md](https://www.angelcruz.dev/sitemap.md)

Canónico HTML: [https://www.angelcruz.dev/post/aprende-laravel-validacion](https://www.angelcruz.dev/post/aprende-laravel-validacion)
