Laravel
Tutorial Laravel: Validaciones de datos en controladores y formularios
Laravel simplifica validaciones de datos con reglas como `required`, `email` en formularios y controladores PHP. Domina estas reglas y mejora la calidad de tus formularios desde hoy.
Aprende Laravel GRATIS y certifícateReglas de validación básicas
Laravel ofrece un sistema de validación elegante y sencillo que facilita la comprobación de datos entrantes en las aplicaciones. Las reglas de validación básicas permiten asegurarse de que los datos proporcionados por los usuarios cumplen con los requisitos establecidos.
Para validar datos en un controlador, se utiliza el método $request->validate()
. Este método acepta un array donde las claves son los nombres de los campos y los valores son las reglas de validación aplicables. Por ejemplo:
public function store(Request $request)
{
$validatedData = $request->validate([
'nombre' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed',
]);
// Lógica para guardar los datos validados
}
En este ejemplo:
required
: indica que el campo es obligatorio.string
: verifica que el campo es una cadena de caracteres.max:255
: establece un máximo de 255 caracteres.email
: comprueba que el formato sea un correo electrónico válido.unique:users
: asegura que el valor sea único en la tablausers
.min:8
: requiere un mínimo de 8 caracteres.confirmed
: espera que exista un campopassword_confirmation
y que coincida conpassword
.
Las reglas de validación pueden combinarse utilizando el carácter |
para aplicar múltiples restricciones a un solo campo. Es importante especificar todas las reglas necesarias para garantizar la integridad de los datos.
Además de las reglas básicas, Laravel proporciona una variedad de reglas predefinidas como:
numeric
: el campo debe ser numérico.date
: el campo debe ser una fecha válida.boolean
: el campo debe ser verdadero o falso.accepted
: el campo debe ser "yes", "on", 1 o true (útil para términos y condiciones).
Para validar que un campo sea opcional pero, si está presente, cumpla ciertas reglas, se utiliza la regla nullable
. Por ejemplo:
$validatedData = $request->validate([
'telefono' => 'nullable|numeric',
]);
Aquí, telefono
no es obligatorio, pero si se proporciona, debe ser numérico.
También es posible usar arreglos para definir las reglas, lo que facilita agregar condiciones complejas:
$validatedData = $request->validate([
'nombre' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'unique:users'],
]);
Este formato permite una mayor legibilidad y facilita la aplicación de reglas que contienen dos puntos o comas internas.
Laravel permite crear mensajes de error personalizados y utilizar reglas avanzadas, pero las reglas básicas son fundamentales para asegurar la calidad de los datos desde el principio. Es esencial familiarizarse con ellas para garantizar que las aplicaciones sean robustas y seguras.
Mensajes de error personalizados
Al validar datos en Laravel, es posible que los mensajes de error predeterminados no sean suficientes para proporcionar una experiencia de usuario óptima. Personalizar los mensajes de error permite ofrecer información más clara y específica, mejorando la usabilidad de la aplicación.
Para definir mensajes de error personalizados, se puede pasar un segundo parámetro al método $request->validate()
que contenga un array de mensajes. Por ejemplo:
public function store(Request $request)
{
$validatedData = $request->validate([
'nombre' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed',
], [
'nombre.required' => 'El campo nombre es obligatorio.',
'nombre.max' => 'El nombre no puede exceder de 255 caracteres.',
'email.required' => 'Por favor, introduce una dirección de correo electrónico.',
'email.email' => 'Introduce una dirección de correo electrónico válida.',
'email.unique' => 'Este correo electrónico ya está registrado.',
'password.required' => 'Es necesario establecer una contraseña.',
'password.min' => 'La contraseña debe tener al menos 8 caracteres.',
'password.confirmed' => 'Las contraseñas no coinciden.',
]);
// Lógica para guardar los datos validados
}
En este ejemplo:
- Las claves del array de mensajes personalizados siguen el formato
campo.regla
. - Se proporciona un mensaje específico para cada regla de validación aplicada a un campo.
- Al utilizar mensajes personalizados, los usuarios reciben retroalimentación clara sobre los errores en el formulario.
Además, es posible definir mensajes genéricos para una regla sin especificar el campo. Por ejemplo:
$validatedData = $request->validate([
'edad' => 'required|integer|min:18',
], [
'integer' => 'El campo :attribute debe ser un número entero.',
'edad.required' => 'Por favor, indica tu edad.',
'edad.min' => 'Debes tener al menos 18 años.',
]);
En este caso, cualquier campo que falle la regla integer
mostrará el mensaje genérico. El marcador :attribute
será reemplazado por el nombre del campo correspondiente.
Para traducir o modificar los mensajes predeterminados en toda la aplicación, Laravel utiliza archivos de lenguaje ubicados en resources/lang/<idioma>/validation.php
. Allí se pueden ajustar los mensajes y atributos de forma global.
Por ejemplo, para cambiar el nombre de los atributos y que aparezcan más amigables en los mensajes de error, se puede modificar el array attributes
:
// resources/lang/es/validation.php
'attributes' => [
'email' => 'correo electrónico',
'password' => 'contraseña',
'edad' => 'edad',
],
Así, un mensaje como "El campo email es obligatorio" se convertirá en "El campo correo electrónico es obligatorio".
También es posible personalizar los mensajes para reglas específicas y añadir traducciones. Por ejemplo, para ajustar el mensaje de la regla required
:
// resources/lang/es/validation.php
'required' => 'El campo :attribute es obligatorio.',
En situaciones donde se necesita una mayor flexibilidad, se pueden utilizar clausuras para definir mensajes de validación personalizados. Por ejemplo:
Validator::extend('mayor_de_edad', function ($attribute, $value, $parameters, $validator) {
return \Carbon\Carbon::parse($value)->age >= 18;
});
$validatedData = $request->validate([
'fecha_nacimiento' => 'required|date|mayor_de_edad',
], [
'fecha_nacimiento.mayor_de_edad' => 'Debes ser mayor de edad para registrarte.',
]);
En este ejemplo, se crea una regla personalizada mayor_de_edad
y se define un mensaje específico para ella.
Personalizar los mensajes de error es crucial para proporcionar una experiencia de usuario óptima y garantizar que los usuarios comprendan fácilmente las correcciones necesarias en los formularios. Aprovechar las capacidades de Laravel en este aspecto facilita el desarrollo de aplicaciones más intuitivas y amigables.
Validación en Form Requests
Para mantener los controladores limpios y organizar la lógica de validación, Laravel introduce las Form Requests. Estas son clases especializadas que encapsulan las reglas de validación y la lógica de autorización de una solicitud HTTP, permitiendo separar la validación del controlador.
Para crear una Form Request, se utiliza el comando Artisan:
php artisan make:request StoreUserRequest
Este comando genera una nueva clase en app/Http/Requests/StoreUserRequest.php
. Dentro de esta clase, se definen las reglas de validación en el método rules()
:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUserRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'nombre' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed',
];
}
}
El método authorize()
determina si el usuario está autorizado para realizar esta solicitud. Por defecto, devuelve false
, por lo que es importante establecerlo en true
o implementar la lógica de autorización necesaria.
Una vez creada la Form Request, se puede inyectar en el método del controlador en lugar de la instancia de Request
:
use App\Http\Requests\StoreUserRequest;
class UserController extends Controller
{
public function store(StoreUserRequest $request)
{
// Los datos ya han sido validados
$data = $request->validated();
// Lógica para crear el usuario
User::create($data);
// Retornar respuesta o redireccionar
}
}
Al utilizar la Form Request, Laravel ejecuta automáticamente la validación antes de que se ejecute el método del controlador. Si la validación falla, se redirige al usuario de vuelta con los mensajes de error correspondientes.
Además de las reglas, es posible personalizar los mensajes de error dentro de la Form Request utilizando el método messages()
:
public function messages()
{
return [
'nombre.required' => 'El campo nombre es obligatorio.',
'email.required' => 'El correo electrónico es obligatorio.',
'email.email' => 'Introduce una dirección de correo electrónico válida.',
'email.unique' => 'Este correo ya está registrado.',
'password.required' => 'La contraseña es obligatoria.',
'password.min' => 'La contraseña debe tener al menos 8 caracteres.',
'password.confirmed'=> 'Las contraseñas no coinciden.',
];
}
De esta manera, se centralizan las reglas y los mensajes de validación, mejorando la mantenibilidad del código y facilitando futuras modificaciones.
Las Form Requests también permiten personalizar los nombres de los atributos en los mensajes de error mediante el método attributes()
:
public function attributes()
{
return [
'nombre' => 'nombre completo',
'password' => 'contraseña',
];
}
Esto mejora la claridad en los mensajes de error, haciendo que sean más intuitivos para el usuario final.
Para aplicar lógica de autorización en el método authorize()
, se pueden realizar verificaciones adicionales. Por ejemplo, para permitir solo a usuarios autenticados:
public function authorize()
{
return auth()->check();
}
Si authorize()
retorna false
, Laravel lanzará una excepción AuthorizationException
, impidiendo el procesamiento de la solicitud y mostrando un error 403.
Es posible también preparar o modificar los datos antes de la validación utilizando el método prepareForValidation()
:
protected function prepareForValidation()
{
$this->merge([
'email' => strtolower($this->email),
]);
}
Este enfoque permite normalizar los datos de entrada antes de aplicar las reglas de validación, asegurando consistencia en la aplicación.
Las Form Requests son especialmente útiles cuando se requiere la misma validación en múltiples lugares. Al reutilizar la misma clase, se evita la duplicación de código y se mejora la eficiencia del desarrollo.
Además, se pueden incorporar reglas de validación condicionales dentro de la Form Request utilizando el método withValidator()
:
public function withValidator($validator)
{
$validator->sometimes('empresa', 'required', function ($input) {
return $input->tipo_usuario === 'empresa';
});
}
En este ejemplo, el campo empresa
es obligatorio solo si tipo_usuario
es igual a 'empresa'
, permitiendo crear validaciones dinámicas en función de los datos de la solicitud.
En resumen, las Form Requests proporcionan una forma estructurada de gestionar la validación y autorización en Laravel. Al utilizarlas, se mejora la legibilidad y se mantiene un código más limpio y modular, facilitando el mantenimiento y la ampliación de las funcionalidades de la aplicación.
Manejo de errores y “old inputs”
Al validar formularios en Laravel, es común que los usuarios cometan errores al ingresar datos. Es importante proporcionar una retroalimentación adecuada y mantener los datos previamente ingresados para mejorar la experiencia del usuario.
Cuando la validación falla, Laravel redirige automáticamente de vuelta a la página anterior con los errores de validación y los datos antiguos (old inputs) en la sesión. Esto permite mostrar mensajes de error y repoblar los campos del formulario con la información que el usuario ingresó.
Para mostrar los mensajes de errores en las vistas Blade, se puede utilizar la variable global $errors
, que es una instancia de Illuminate\Support\ViewErrorBag
. Por ejemplo, para mostrar todos los errores, se puede hacer lo siguiente:
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
Este bloque verifica si hay errores y los muestra en una lista no ordenada, proporcionando información clara al usuario sobre qué campos necesitan corrección.
Para repoblar los campos del formulario con los datos antiguos, se utiliza la función old()
. Esta función devuelve el valor anterior del campo, si está disponible. Por ejemplo:
<input type="text" name="nombre" value="{{ old('nombre') }}" />
De esta manera, si la validación falla, el campo nombre
conservará el valor que el usuario ingresó previamente, evitando que tenga que volver a escribirlo.
Es recomendable utilizar las clases de error en los elementos del formulario para resaltar los campos problemáticos. Por ejemplo, agregando una clase CSS cuando hay errores en un campo específico:
<input type="text" name="email" value="{{ old('email') }}" class="@error('email') is-invalid @enderror" />
Aquí, la directiva @error('email')
verifica si hay un error asociado al campo email
. Si es así, se añade la clase is-invalid
, que puede estilizarse en CSS para resaltar el campo.
Además, para mostrar el mensaje de error específico de un campo, se puede utilizar:
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
La variable $message
contiene el mensaje de error asociado al campo email
, permitiendo mostrarlo justo debajo del campo correspondiente.
En el controlador, al aplicar la validación, no es necesario realizar ninguna acción adicional para manejar los errores y los old inputs, ya que Laravel se encarga de ello automáticamente cuando se utiliza el método $request->validate()
o las Form Requests. Si la validación falla, Laravel redirige de vuelta y almacena tanto los errores como los datos anteriores en la sesión.
Es posible personalizar el comportamiento después de una falla de validación. Por ejemplo, si se desea redirigir a una ruta específica, se puede capturar la excepción ValidationException
y modificar la respuesta:
use Illuminate\Validation\ValidationException;
public function store(Request $request)
{
try {
$validated = $request->validate([
// reglas de validación
]);
// Procesar los datos validados
} catch (ValidationException $e) {
return redirect('/ruta-específica')
->withErrors($e->validator)
->withInput();
}
}
Sin embargo, en la mayoría de los casos, dejar que Laravel maneje la redirección y los errores es la opción más sencilla y efectiva.
También es posible acceder a los errores de validación en el lado del cliente mediante JavaScript si es necesario. Los errores se pueden pasar al script y manejarlos para proporcionar una experiencia de usuario más dinámica.
Validación avanzada y validadores personalizados
Además de las reglas de validación básicas, Laravel ofrece herramientas para implementar validaciones avanzadas y crear validadores personalizados. Estas funcionalidades permiten manejar escenarios complejos y adaptarse a requisitos específicos de la aplicación.
Validación condicional
Laravel permite aplicar reglas de validación basadas en ciertas condiciones utilizando el método sometimes()
. Este método es útil cuando se necesita validar campos solo si se cumplen ciertas condiciones en los datos de entrada.
Por ejemplo, supongamos que queremos validar un campo empresa
solo si el usuario selecciona el tipo de usuario "empresa":
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'tipo_usuario' => 'required|string',
]);
$validator->sometimes('empresa', 'required|string', function ($input) {
return $input->tipo_usuario === 'empresa';
});
$validatedData = $validator->validate();
// Procesar los datos validados
}
En este ejemplo:
- Se crea un validador manualmente utilizando
Validator::make()
. - Se aplican las reglas de validación básicas al campo
tipo_usuario
. - El método
sometimes()
agrega una regla al campoempresa
solo cuando la función de cierre devuelvetrue
. - La función de cierre verifica si
tipo_usuario
es igual a "empresa".
Reglas de validación complejas
Para casos donde las reglas de validación son muy detalladas, es posible utilizar la clase Illuminate\Validation\Rule
. Esto permite construir reglas complejas de forma más legible.
Por ejemplo, para validar que un campo username
no contenga espacios y tenga una longitud específica:
use Illuminate\Validation\Rule;
public function store(Request $request)
{
$validatedData = $request->validate([
'username' => [
'required',
'alpha_num',
'min:4',
'max:20',
function ($attribute, $value, $fail) {
if (strpos($value, ' ') !== false) {
$fail('El :attribute no puede contener espacios.');
}
},
],
]);
// Procesar los datos validados
}
En este caso:
- Se utiliza una clausura dentro del array de reglas para agregar una validación personalizada.
- La clausura recibe el nombre del atributo, el valor y una función
$fail
para indicar que la validación ha fallado. - Si el
username
contiene espacios, se invoca$fail()
con un mensaje de error personalizado.
Creación de reglas de validación personalizadas
Laravel permite crear reglas de validación personalizadas como clases independientes. Esto es útil para reutilizar la regla en múltiples lugares y mantener un código más organizado.
Para generar una regla personalizada, se utiliza Artisan:
php artisan make:rule DocumentoIdentidad
Este comando crea una nueva clase en app/Rules/DocumentoIdentidad.php
. La clase implementa la interfaz Illuminate\Contracts\Validation\Rule
y debe definir los métodos passes()
y message()
:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class DocumentoIdentidad implements Rule
{
public function passes($attribute, $value)
{
// Lógica de validación
return preg_match('/^[0-9]{8}[A-Z]$/', $value);
}
public function message()
{
return 'El :attribute no es un documento de identidad válido.';
}
}
En este ejemplo:
- El método
passes()
contiene la lógica para validar el valor. Devuelvetrue
si es válido ofalse
en caso contrario. - El método
message()
proporciona el mensaje de error que se mostrará si la validación falla. - La regla verifica que el campo siga un patrón específico, por ejemplo, 8 dígitos seguidos de una letra mayúscula.
Para utilizar esta regla personalizada en el controlador:
use App\Rules\DocumentoIdentidad;
public function store(Request $request)
{
$validatedData = $request->validate([
'dni' => ['required', new DocumentoIdentidad],
]);
// Procesar los datos validados
}
Validación de arrays y campos anidados
Cuando se trabaja con arrays de datos o campos anidados en formularios, Laravel proporciona una sintaxis especial para validar cada elemento del array.
Por ejemplo, para validar múltiples direcciones de correo electrónico:
public function store(Request $request)
{
$validatedData = $request->validate([
'emails' => 'required|array',
'emails.*' => 'email|distinct',
]);
// Procesar los datos validados
}
Aquí:
- La regla
'emails' => 'required|array'
asegura que el campoemails
es un array y es obligatorio. - La regla
'emails.*' => 'email|distinct'
aplica las reglas a cada elemento del array: email
: cada elemento debe ser un correo electrónico válido.distinct
: los valores deben ser únicos dentro del array.
Para validar campos anidados en un array multidimensional:
public function store(Request $request)
{
$validatedData = $request->validate([
'productos' => 'required|array',
'productos.*.nombre' => 'required|string',
'productos.*.precio' => 'required|numeric|min:0',
'productos.*.cantidad' => 'required|integer|min:1',
]);
// Procesar los datos validados
}
En este caso:
- Se valida que
productos
es un array obligatorio. - Para cada elemento del array
productos
, se validan los camposnombre
,precio
ycantidad
. - Las reglas aseguran que se proporcionen todos los datos necesarios para cada producto.
Reglas de validación basadas en datos externos
A veces es necesario validar un campo en función de datos que no están en la solicitud, como valores de la base de datos o servicios externos. Para ello, se pueden utilizar reglas con dependencias u objetos validador.
Por ejemplo, para verificar que un código promocional es válido:
use App\Models\Promocion;
public function store(Request $request)
{
$validatedData = $request->validate([
'codigo' => [
'required',
function ($attribute, $value, $fail) {
if (!Promocion::where('codigo', $value)->exists()) {
$fail('El código promocional no es válido.');
}
},
],
]);
// Procesar los datos validados
}
En este ejemplo:
- Se utiliza una clausura para acceder al modelo
Promocion
y comprobar si el código existe en la base de datos. - Si el código no existe, se llama a
$fail()
con un mensaje de error.
Mensajes de error personalizados en reglas personalizadas
Al crear reglas personalizadas, es posible proporcionar mensajes de error específicos en función de condiciones particulares. Esto se logra modificando el método message()
en la clase de la regla.
Por ejemplo, para una regla que valida números de teléfono:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class NumeroTelefono implements Rule
{
protected $pais;
public function __construct($pais = 'ES')
{
$this->pais = $pais;
}
public function passes($attribute, $value)
{
// Lógica que valida el número según el país
return validarNumeroTelefono($value, $this->pais);
}
public function message()
{
return 'El :attribute no es un número de teléfono válido en ' . $this->pais . '.';
}
}
Al utilizar la regla en el controlador, se puede especificar el país:
use App\Rules\NumeroTelefono;
public function store(Request $request)
{
$validatedData = $request->validate([
'telefono' => ['required', new NumeroTelefono('FR')],
]);
// Procesar los datos validados
}
De esta manera:
- La regla personaliza el mensaje de error según el país especificado.
- Se logra una validación más precisa y mensajes más informativos para el usuario.
Personalización del validador
Laravel permite extender y personalizar el comportamiento del validador mediante la modificación del servicio de validación en un proveedor de servicios (ServiceProvider
).
Por ejemplo, se puede registrar una nueva regla de validación global en el método boot()
de AppServiceProvider
:
use Illuminate\Support\Facades\Validator;
public function boot()
{
Validator::extend('mayor_de_edad', function ($attribute, $value, $parameters, $validator) {
return \Carbon\Carbon::parse($value)->age >= 18;
}, 'Debes ser mayor de edad.');
Validator::replacer('mayor_de_edad', function ($message, $attribute, $rule, $parameters) {
return str_replace(':attribute', $attribute, $message);
});
}
En este ejemplo:
- Se crea una nueva regla
mayor_de_edad
que verifica si la edad es mayor o igual a 18 años. - Se registra un reemplazador de mensajes para personalizar el mensaje de error.
Luego, se puede utilizar la nueva regla en cualquier lugar de la aplicación:
$validatedData = $request->validate([
'fecha_nacimiento' => 'required|date|mayor_de_edad',
]);
Utilizando validadores después del primer fallo
Por defecto, Laravel detiene el proceso de validación en el primer fallo por campo. Para cambiar este comportamiento y obtener todos los errores posibles, se puede utilizar el método validate()
del objeto Validator
en lugar de $request->validate()
.
use Illuminate\Support\Facades\Validator;
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'nombre' => 'required|string',
'email' => 'required|email',
]);
$validator->stopOnFirstFailure(false);
$validatedData = $validator->validate();
// Procesar los datos validados
}
Aquí:
- El método
stopOnFirstFailure(false)
indica que el validador debe continuar validando todos los campos, incluso si alguno falla. - Se recopilan todos los errores de validación para proporcionarlos al usuario.
Validación de archivos y subida de documentos
Para validar archivos subidos, Laravel ofrece reglas específicas que permiten verificar el tipo, tamaño y dimensiones de los archivos.
Por ejemplo, para validar una imagen de perfil:
public function store(Request $request)
{
$validatedData = $request->validate([
'avatar' => 'required|image|mimes:jpeg,png,jpg,gif|dimensions:min_width=100,min_height=100|max:2048',
]);
// Procesar el archivo subido
}
En este caso:
image
: verifica que el archivo es una imagen.mimes
: especifica los tipos MIME permitidos.dimensions
: establece dimensiones mínimas para la imagen.max
: limita el tamaño máximo del archivo en kilobytes (2048 KB en este ejemplo).
Todas las lecciones de Laravel
Accede a todas las lecciones de Laravel y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Php Laravel
Introducción Y Entorno
Instalación Y Configuración Laravel
Introducción Y Entorno
Controladores Mvc
Controladores Http
Vistas Y Blade Templates
Controladores Http
Formularios Y Validación
Controladores Http
Controladores Rest
Controladores Http
Middleware Y Control De Solicitudes
Persistencia
Seguridad Autenticación Y Autorización
Persistencia
Bases De Datos Y Eloquent Orm
Persistencia
Relaciones Entre Modelos
Persistencia
Consultas Avanzadas
Persistencia
Colecciones Y Métodos Avanzados
Persistencia
Migraciones Y Seeders
Persistencia
Sistema De Autenticación Nativo Laravel
Middlewares Y Seguridad
Autorización (Policies Y Gates)
Middlewares Y Seguridad
Csrf Y Protección De Formularios En Blade
Middlewares Y Seguridad
Validaciones De Datos En Controladores Y Formularios
Middlewares Y Seguridad
Cifrado De Contraseñas
Middlewares Y Seguridad
Autenticación Jwt En Api Rest
Middlewares Y Seguridad
Pruebas Unitarias Con Phpunit
Testing
Pruebas De Integración En Laravel
Testing
En esta lección
Objetivos de aprendizaje de esta lección
- Conocer las reglas básicas de validación de Laravel, como
required
,email
,unique
, y sus funcionalidades. - Aprender a validar datos recibidos en controladores utilizando
$request->validate()
. - Entender la combinación de reglas para validaciones múltiples y su sintaxis.
- Explorar la creación de mensajes de error personalizados para mejorar la experiencia del usuario.