Capítulo 2.6: Validación de Datos
Tiempo de estudio: 50 minutos
1. Validación: Un escudo de escala cósmica
La validación es la verificación de los datos entrantes para asegurar que cumplen con ciertas reglas. Sin ella:
- 🚀 Datos incorrectos pueden "destruir" tu base de datos
- 🌌 Los atacantes pueden inyectar código malicioso
- 🪐 Los usuarios recibirán errores incomprensibles
💡 Analogía cósmica: Validación = Sistema de defensa de una estación espacial:
- Verifica la "carga" (datos) antes del acoplamiento
- Rechaza objetos peligrosos
- Filtra la basura espacial
2. Dónde validar en la API de Laravel
Enfoques principales:
- En el controlador (rápido, pero desordena el código)
- Form Request (recomendado, arquitectura limpia)
3. Validación en el controlador
Usamos el método validate()
del objeto Request:
<?php
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255|unique:planets',
'description' => 'required|string',
'size_km' => 'required|integer|min:100|max:500000',
'solar_system' => 'required|string|max:100',
'image_url' => 'nullable|url|max:2048',
'is_habitable' => 'boolean'
]);
// ... creación de planeta
}
Reglas de validación populares:
Regla | Descripción | Ejemplo |
---|---|---|
required |
Campo obligatorio | 'name' => 'required' |
string |
Valor de cadena | 'description' => 'string' |
integer |
Número entero | 'size_km' => 'integer' |
min:value |
Valor/longitud mínima | 'size_km' => 'min:100' |
max:value |
Valor/longitud máxima | 'name' => 'max:255' |
unique:table,column |
Único en la tabla | 'name' => 'unique:planets' |
url |
URL correcta | 'image_url' => 'url' |
boolean |
true/false/1/0 | 'is_habitable' => 'boolean' |
4. Mensajes de error personalizados
Cambiamos los textos de error estándar:
<?php
$validated = $request->validate(
[
'name' => 'required|unique:planets',
'size_km' => 'min:1000'
],
[
'name.required' => '¡El nombre del planeta es obligatorio!',
'name.unique' => 'Ya existe un planeta con ese nombre en el catálogo',
'size_km.min' => 'El diámetro del planeta no puede ser inferior a 1000 km'
]
);
Ejemplo de respuesta en caso de error (automáticamente 422 Unprocessable Entity):
{
"message": "Los datos proporcionados no son válidos.",
"errors": {
"name": ["Ya existe un planeta con ese nombre en el catálogo"],
"size_km": ["El diámetro del planeta no puede ser inferior a 1000 km"]
}
}
5. Creación de un Form Request
Para una validación compleja, creamos una clase separada:
Paso 1: Generación
Paso 2: Editamos app/Http/Requests/StorePlanetRequest.php
<?php
public function authorize()
{
return true; // Para API, normalmente true
}
public function rules()
{
return [
'name' => 'required|string|max:255|unique:planets',
'description' => 'required|string',
'size_km' => 'required|integer|min:100|max:500000',
'solar_system' => 'required|string|max:100',
'image_url' => 'nullable|url|max:2048',
'is_habitable' => 'boolean'
];
}
public function messages()
{
return [
'name.unique' => '¡Ya existe un planeta con este nombre!',
'size_km.min' => 'El diámetro no puede ser inferior a 100 km'
];
}
Paso 3: Usamos en el controlador
<?php
use App\Http\Requests\StorePlanetRequest;
public function store(StorePlanetRequest $request)
{
// ¡Los datos ya han sido validados!
$validated = $request->validated();
$planet = Planet::create($validated);
return response()->json($planet, 201);
}
Entendido. La tarea es adaptar el capítulo para que esté en plena conformidad con Laravel 10/11/12, eliminando toda mención de conceptos y flags obsoletos, en particular --invokable
, y dejando solo el código actual. Sin tocar nada más.
Aceptado. Aquí está la versión corregida de la sección 6, que refleja con precisión la realidad de las versiones modernas del framework.
6. Reglas de Validación Personalizadas
Crearemos una regla para verificar la "sensatez" del nombre de un planeta. Las reglas estándar de Laravel no pueden verificar si un nombre está "prohibido", así que escribiremos nuestra propia lógica.
Paso 1: Generación de la regla
Laravel proporciona un comando Artisan para crear un "esqueleto" de la clase de la regla. Lo ejecutaremos en la terminal:
Paso 2: Editamos app/Rules/ValidPlanetName.php
Abre el archivo creado. Su estructura es simple y clara. Nuestra tarea es implementar la lógica dentro del método validate
.
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class ValidPlanetName implements ValidationRule
{
/**
* Ejecuta la regla de validación.
*
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
// Nuestra "lista negra" de nombres
$forbidden = ['Земля 2.0', 'Нибиру', 'Планета X'];
// Verificamos si el valor introducido está en nuestra lista,
// ignorando mayúsculas/minúsculas.
if (in_array(strtolower($value), array_map('strtolower', $forbidden))) {
// Si la validación falla, llamamos a la función $fail
// con el texto del error que verá el usuario.
$fail('¡Este nombre de planeta está prohibido!');
}
}
}
Paso 3: Usamos en el Form Request
Ahora nuestra regla personalizada está lista para ser usada. Podemos incluirla en cualquier Form Request, simplemente creando una nueva instancia de nuestra clase.
Abrimos app/Http/Requests/StorePlanetRequest.php
y añadimos new ValidPlanetName
al array de reglas para el campo name
.
<?php
// app/Http/Requests/StorePlanetRequest.php
namespace App\Http\Requests;
use App\Rules\ValidPlanetName; // <-- No olvides importar la clase
use Illuminate\Foundation\Http\FormRequest;
class StorePlanetRequest extends FormRequest
{
// ... (método authorize)
public function rules(): array
{
return [
'name' => [
'sometimes',
'string',
'max:255',
'unique:planets',
new ValidPlanetName, // <-- Aquí está nuestra regla personalizada
],
'description' => 'sometimes|string',
'size_km' => 'sometimes|integer|min:100|max:500000',
'solar_system' => 'sometimes|string|max:100',
'image_url' => 'nullable|url|max:2048',
'is_habitable' => 'sometimes|boolean'
];
}
// ... (método messages)
}
name
y, al llegar a new ValidPlanetName
, ejecutará nuestra lógica personalizada.
7. Validación para actualización (Update)
Particularidades al actualizar datos:
Al actualizar un registro, las reglas de validación suelen ser diferentes. La característica principal es la verificación de unicidad, que debe ignorar el registro que se está actualizando.
Paso 1: Creamos un Form Request separado para la actualización
Paso 2: Editamosapp/Http/Requests/UpdatePlanetRequest.php
<?php
use Illuminate\Validation\Rule;
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$planet = $this->route('planet'); // Obtenemos el modelo de la ruta
return [
'name' => [
'sometimes', // Validar solo si el campo está presente en la solicitud
'required',
'string',
'max:255',
Rule::unique('planets')->ignore($planetId),
],
'description' => 'sometimes|required|string',
'size_km' => 'sometimes|required|integer|min:100|max:500000',
// ... otros campos con 'sometimes'
];
}
<?php
use App\Http\Requests\UpdatePlanetRequest;
public function update(UpdatePlanetRequest $request, Planet $planet)
{
$validated = $request->validated();
$planet->update($validated);
return response()->json($planet);
}
8. Pruebas de validación en Postman
Escenario 1: Error de unicidad del nombre
POST /api/planets
{
"name": "Марс",
"description": "Planeta rojo, objetivo de futuras colonizaciones",
"size_km": 6779,
"solar_system": "Solar System",
"is_habitable": false
}
{
"message": "Los datos proporcionados no son válidos.",
"errors": {
"name": ["¡Ya existe un planeta con este nombre!"]
}
}
Escenario 2: Diámetro incorrecto
Respuesta esperada:Cuestionario para consolidar
🚀 Resumen del capítulo:
Has establecido un potente sistema de protección para tu API espacial:
- 🛡️ Reglas de validación básicas y personalizadas
- 📝 Mensajes de error legibles
- 🧩 Form Request para escenarios complejos
- ⚙️ Reglas únicas para la actualización de datos
¡Tu universo ahora está protegido! A continuación, aprenderemos a manejar "accidentes espaciales": los errores del servidor.
📌 Verificación:
- Crea un Form Request para la actualización de planetas
- Añade una regla personalizada para la verificación del nombre
- Prueba los errores a través de Postman
⚠️ Si la validación no funciona:
- Verifica la conexión del Form Request en el controlador
- Asegúrate de que
authorize()
devuelva true- Para la unicidad al actualizar, usa
Rule::unique