> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Validación

> Explicamos cómo validar los datos enviados por formularios con las funciones de validación de Laravel.

## ¿Qué es la validación?

Validar consiste en comprobar que los datos enviados por el usuario cumplen el formato y las condiciones esperadas.
Laravel ofrece validación sencilla y potente mediante el método `validate` del objeto Request o mediante clases form request dedicadas.

```mermaid theme={null}
flowchart TD
    A["Solicitud HTTP recibida"] --> B["Se aplican las reglas de validación"]
    B --> C{{"¿Pasa la<br>validación?"}}
    C -->|"Éxito"| D["Obtiene los datos validados"]
    D --> E["Ejecuta la lógica del controlador"]
    E --> F["Respuesta de éxito"]
    C -->|"Fallo<br>(solicitud Web)"| G["Redirige a la pantalla anterior<br>Errores en la sesión"]
    C -->|"Fallo<br>(solicitud API)"| H["422 Unprocessable Entity<br>Respuesta JSON de error"]
```

## Validación en el controlador

### Uso de `$request->validate()`

Llamar a `$request->validate()` en el método del controlador es la forma más sencilla.
Ante un fallo, Laravel redirige automáticamente a la pantalla anterior y guarda los errores en la sesión.

Define las rutas:

```php theme={null}
use App\Http\Controllers\PostController;

Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);
```

Crea el controlador:

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    public function create(): View
    {
        return view('post.create');
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'body'  => 'required|string',
            'email' => 'required|email',
        ]);

        // Guarda el post con los datos validados...

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

`validate` recibe un array cuya clave es el campo y cuyo valor son las reglas.
Las reglas se separan con `|` o se pasan como array.

```php theme={null}
// Separadas por tuberías
'title' => 'required|string|max:255',

// Como array
'title' => ['required', 'string', 'max:255'],
```

### Reglas de validación principales

| Regla          | Descripción                                 |
| -------------- | ------------------------------------------- |
| `required`     | El valor está presente y no vacío           |
| `string`       | Es un string                                |
| `email`        | Formato de correo válido                    |
| `min:valor`    | Longitud o valor numérico mínimo            |
| `max:valor`    | Longitud o valor numérico máximo            |
| `unique:tabla` | El valor es único en la tabla               |
| `nullable`     | Se permite `null`                           |
| `integer`      | Es entero                                   |
| `boolean`      | Booleano (`true`/`false`, `1`/`0`, etc.)    |
| `date`         | Formato de fecha válido                     |
| `confirmed`    | Coincide con el campo `nombre_confirmation` |

<Info>
  Consulta la lista completa en la [documentación oficial](https://laravel.com/docs/validation#available-validation-rules).
</Info>

### Uso de los datos validados

El retorno de `validate` es un array solo con los datos que pasaron la validación.
Puedes usarlos como datos de confianza.

```php theme={null}
$validated = $request->validate([
    'title' => 'required|string|max:255',
    'body'  => 'required|string',
]);

// $validated con formato ['title' => '...', 'body' => '...']
Post::create($validated);
```

## Mostrar errores en Blade

Ante un fallo, Laravel hace la variable `$errors` disponible en todas las vistas.
Lo gestiona el middleware `ShareErrorsFromSession` del grupo `web`.

### Listar todos los errores

```blade theme={null}
@if ($errors->any())
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif
```

### Mostrar el error de un campo

Con la directiva `@error` muestras el error de un campo en línea.

```blade theme={null}
<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="error-message">{{ $message }}</div>
@enderror
```

<Tip>
  Con `old('nombre_del_campo')` puedes volver a rellenar el valor introducido por el usuario tras un fallo de validación.
</Tip>

## Form requests

### ¿Qué es una form request?

Cuando la lógica de validación se vuelve compleja, extraerla a una clase "form request" es una buena opción.
Una form request es una clase de solicitud personalizada que agrupa validación y autorización.

```mermaid theme={null}
flowchart TD
    A["Llamada al método del controlador"] --> B["Instancia FormRequest"]
    B --> C["Ejecuta authorize()"]
    C --> D{{"¿Autoriza?"}}
    D -->|"false"| E["403 Forbidden"]
    D -->|"true"| F["Ejecuta rules()"]
    F --> G["Ejecuta validación"]
    G --> H{{"¿Pasa la<br>validación?"}}
    H -->|"Fallo"| I["Respuesta de error<br>de validación"]
    H -->|"Éxito"| J["Ejecuta el método del controlador"]
```

### Crear una form request

Genera la clase con el comando Artisan `make:request`.

```shell theme={null}
php artisan make:request StorePostRequest
```

Se crea `app/Http/Requests/StorePostRequest.php`.

```php theme={null}
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
    /**
     * Determina si el usuario está autorizado a realizar esta solicitud
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Devuelve las reglas de validación a aplicar
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'title' => 'required|string|max:255',
            'body'  => 'required|string',
            'email' => 'required|email|unique:posts',
        ];
    }
}
```

### El método `rules()`

Devuelve las reglas de validación como array. El formato es el mismo que en `validate`.

### El método `authorize()`

Determina si la solicitud está autorizada.
Si devuelve `true`, la autorización pasa; si devuelve `false`, se responde automáticamente con 403.

Para permitir solo a usuarios autenticados, puedes comprobar con `auth()->check()`.
En tutoriales basta con devolver `true`.

<Warning>
  Si `authorize` devuelve `false`, el método del controlador no se ejecuta y se responde 403 Forbidden.
</Warning>

### Inyección en el controlador

Basta con tipar la form request en el método del controlador para usarla.
La validación se ejecuta antes de entrar al método, así que no necesitas escribir código de validación dentro.

```php theme={null}
use App\Http\Requests\StorePostRequest;

class PostController extends Controller
{
    public function store(StorePostRequest $request): RedirectResponse
    {
        // Al llegar aquí, ya se validó

        $validated = $request->validated();

        Post::create($validated);

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

Con `$request->validated()` obtienes solo los datos validados.

## Ejemplo práctico: crear y guardar un formulario de post

Flujo completo de visualización, envío, validación y guardado.

<Steps>
  <Step title="Definir las rutas">
    ```php theme={null}
    use App\Http\Controllers\PostController;

    Route::get('/posts/create', [PostController::class, 'create']);
    Route::post('/posts', [PostController::class, 'store']);
    ```
  </Step>

  <Step title="Crear la form request">
    ```shell theme={null}
    php artisan make:request StorePostRequest
    ```

    ```php theme={null}
    public function rules(): array
    {
        return [
            'title' => 'required|string|max:255',
            'body'  => 'required|string',
        ];
    }

    public function authorize(): bool
    {
        return true;
    }
    ```
  </Step>

  <Step title="Implementar el controlador">
    ```php theme={null}
    use App\Http\Requests\StorePostRequest;
    use App\Models\Post;

    class PostController extends Controller
    {
        public function create(): View
        {
            return view('posts.create');
        }

        public function store(StorePostRequest $request): RedirectResponse
        {
            Post::create($request->validated());

            return redirect('/posts');
        }
    }
    ```
  </Step>

  <Step title="Crear la plantilla Blade">
    ```blade theme={null}
    {{-- resources/views/posts/create.blade.php --}}

    <h1>Nuevo post</h1>

    @if ($errors->any())
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    @endif

    <form method="POST" action="/posts">
        @csrf

        <div>
            <label for="title">Título</label>
            <input
                id="title"
                type="text"
                name="title"
                value="{{ old('title') }}"
            />
            @error('title')
                <span>{{ $message }}</span>
            @enderror
        </div>

        <div>
            <label for="body">Cuerpo</label>
            <textarea id="body" name="body">{{ old('body') }}</textarea>
            @error('body')
                <span>{{ $message }}</span>
            @enderror
        </div>

        <button type="submit">Publicar</button>
    </form>
    ```
  </Step>
</Steps>

<Info>
  Incluye siempre `@csrf` en los formularios Blade. Sin el token CSRF, Laravel devuelve un error 419.
</Info>

## Próximos pasos

<Card title="Solicitudes HTTP" icon="arrow-up-from-bracket" href="/es/requests">
  Repasa cómo obtener datos del objeto Request.
</Card>


## Related topics

- [Pruebas HTTP](/es/http-tests.md)
- [Laravel MCP](/es/mcp.md)
- [Laravel Prompts](/es/prompts.md)
- [Reglas de validación personalizadas](/es/advanced/custom-validation-rules.md)
- [Protección CSRF](/es/csrf.md)
