---
description: Crear Form Request con validaciones siguiendo convenciones del proyecto
---

# Crear Form Request

Este workflow crea un Form Request de Laravel con validaciones organizadas por funcionalidad.

## Parámetros Requeridos

- `{Funcionalidad}`: Nombre de la funcionalidad (ej: Users, Products, Orders)
- `{Accion}`: Store, Update, Delete, etc.
- `{Nombre}`: Nombre del recurso en singular (ej: User, Product)

## Pasos

### 1. Crear Form Request

// turbo

```bash
php artisan make:request {Funcionalidad}/{Accion}{Nombre}Request --no-interaction
```

### 2. Implementar Validaciones

Editar `app/Http/Requests/{Funcionalidad}/{Accion}{Nombre}Request.php`:

```php
<?php

declare(strict_types=1);

namespace App\Http\Requests\{Funcionalidad};

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

final class {Accion}{Nombre}Request extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        // Implementar lógica de autorización
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            // Definir reglas aquí
        ];
    }

    /**
     * Get custom messages for validator errors.
     *
     * @return array<string, string>
     */
    public function messages(): array
    {
        return [
            // Mensajes personalizados
        ];
    }

    /**
     * Get custom attributes for validator errors.
     *
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
            // Nombres amigables de atributos
        ];
    }
}
```

### 3. Formatear Código

// turbo

```bash
vendor/bin/pint app/Http/Requests/{Funcionalidad}/{Accion}{Nombre}Request.php
```

## Ejemplos Comunes

### StoreUserRequest

```php
<?php

declare(strict_types=1);

namespace App\Http\Requests\Users;

use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;

final class StoreUserRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()->can('create', User::class);
    }

    /**
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => [
                'required',
                'string',
                'email',
                'max:255',
                Rule::unique('users', 'email'),
            ],
            'password' => ['required', 'confirmed', Password::defaults()],
            'role' => ['required', 'string', Rule::in(['admin', 'user', 'editor'])],
        ];
    }

    /**
     * @return array<string, string>
     */
    public function messages(): array
    {
        return [
            'email.unique' => 'Este correo electrónico ya está registrado.',
            'password.confirmed' => 'Las contraseñas no coinciden.',
        ];
    }

    /**
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
            'name' => 'nombre',
            'email' => 'correo electrónico',
            'password' => 'contraseña',
            'role' => 'rol',
        ];
    }
}
```

### UpdateUserRequest

```php
<?php

declare(strict_types=1);

namespace App\Http\Requests\Users;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;

final class UpdateUserRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()->can('update', $this->route('user'));
    }

    /**
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        $userId = $this->route('user')?->id;

        return [
            'name' => ['sometimes', 'required', 'string', 'max:255'],
            'email' => [
                'sometimes',
                'required',
                'string',
                'email',
                'max:255',
                Rule::unique('users', 'email')->ignore($userId),
            ],
            'password' => ['nullable', 'confirmed', Password::defaults()],
            'role' => ['sometimes', 'required', 'string', Rule::in(['admin', 'user', 'editor'])],
        ];
    }
}
```

## Reglas de Validación Frecuentes

| Regla                 | Descripción                             |
| --------------------- | --------------------------------------- |
| `required`            | Campo obligatorio                       |
| `nullable`            | Puede ser null                          |
| `sometimes`           | Solo validar si está presente           |
| `string`              | Debe ser string                         |
| `email`               | Formato email válido                    |
| `max:255`             | Máximo 255 caracteres                   |
| `min:8`               | Mínimo 8 caracteres                     |
| `confirmed`           | Debe tener campo `{field}_confirmation` |
| `unique:table,column` | Único en tabla                          |
| `exists:table,column` | Debe existir en tabla                   |
| `in:a,b,c`            | Debe ser uno de los valores             |
| `array`               | Debe ser array                          |
| `date`                | Debe ser fecha válida                   |
| `numeric`             | Debe ser numérico                       |
| `boolean`             | Debe ser booleano                       |
| `image`               | Debe ser imagen                         |
| `mimes:jpg,png`       | Tipos MIME permitidos                   |
| `max:2048`            | Tamaño máximo (KB para archivos)        |

## Reglas Personalizadas con Rule::

```php
use Illuminate\Validation\Rule;

// Único ignorando el registro actual
Rule::unique('users', 'email')->ignore($userId);

// Valor debe estar en lista
Rule::in(['admin', 'user', 'editor']);

// Valor no debe estar en lista
Rule::notIn(['banned', 'deleted']);

// Existe en tabla con condición
Rule::exists('posts', 'id')->where('published', true);

// Aplicar regla solo si condición
Rule::when($this->isAdmin(), ['required', 'string']);
```

## Verificación

Después de crear el Form Request, verificar que funciona correctamente:

1. Usar el Form Request en el controller
2. Enviar datos inválidos para ver los errores
3. Verificar que los mensajes personalizados aparecen correctamente
