- Introducción
- Inicio rápido de validación
- Validación de solicitudes de formulario
- Creando validadores manualmente
- Trabajando con los mensajes de error
- Reglas de validación disponibles
- Agregando reglas condicionalmente
- Validando arreglos
- Personalizar las reglas de validación
Introducción
Laravel proporciona varios enfoques diferentes para validar los datos entrantes de tu aplicación. De forma predeterminada, la clase base del controlador de Laravel usa el trait ValidatesRequests
el cual proporciona un método conveniente para validar las solicitudes HTTP entrantes con una variedad de poderosas reglas de validación.
Inicio rápido de validación
Para aprender sobre las poderosas características de validación de Laravel, vamos a observar un ejemplo completo validando un formulario y mostrando los mensajes de error devueltos al usuario.
Definiendo las rutas
Primero, vamos a asumir que tenemos las siguientes rutas definidas en nuestro archivo routes/web.php
:
Route::get('post/create', 'PostController@create'); Route::post('post', 'PostController@store');
La ruta GET
mostrará un formulario al usuario para crear un nuevo post de blog, mientras que la ruta POST
guardará el nuevo post de blog en la base de datos.
Creando el controlador
Luego, vamos a observar un simple controlador que maneja estas rutas. Dejaremos el método store
vacío por ahora:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; class PostController extends Controller { /** * Show the form to create a new blog post. * * @return Response */ public function create() { return view('post.create'); } /** * Store a new blog post. * * @param Request $request * @return Response */ public function store(Request $request) { // Validate and store the blog post... } }
Escribiendo la lógica de validación
Ahora estamos listos para completar nuestro método store
con la lógica para validar el nuevo post de blog. Para hacer esto, usaremos el método validate
proporcionado por el objeto Illuminate\Http\Request
. Si las reglas de validación pasan, tu código continuará su ejecución normalmente; sin embargo, si la validación falla, se arrojará una excepción y la respuesta de error apropiada será devuelta automáticamente al usuario. En el caso de una solicitud HTTP tradicional, se generará una respuesta de redirección, mientras una respuesta JSON será enviada para las solicitudes AJAX.
Para lograr una mejor comprensión del método validate
, regresemos al método store
:
/** * Store a new blog post. * * @param Request $request * @return Response */ public function store(Request $request) { $validatedData = $request->validate([ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); // The blog post is valid... }
Como puedes ver, pasamos las reglas de validación deseadas dentro del método validate
. Otra vez, si la validación falla, se generará la respuesta apropiada automáticamente. Si la validación pasa, nuestro controlador continuará la ejecución normalmente.
Alternativamente, las reglas de validación se pueden especificar como arreglos de reglas en lugar de una sola cadena de caracteres delimitada por |
:
$validatedData = $request->validate([ 'title' => ['required', 'unique:posts', 'max:255'], 'body' => ['required'], ]);
Si quieres especificar el paquete de error en el cual los mensajes de error deberían ser puestos, puedes usar el método validateWithBag
:
$request->validateWithBag('blog', [ 'title' => ['required', 'unique:posts', 'max:255'], 'body' => ['required'], ]);
Deteniendo en la primera falla de validación
Algunas veces puede que desees detener la ejecución de las reglas de validación sobre un atributo después de la primera falla de validación. Para hacer eso, asigna la regla bail
al atributo:
$request->validate([ 'title' => 'bail|required|unique:posts|max:255', 'body' => 'required', ]);
En este ejemplo, si la regla unique
del atributo title
falla, la regla max
no será verificada. Las reglas serán validadas en el orden que sean asignadas.
Una observación sobre los atributos anidados
Si tu solicitud HTTP contiene parámetros «anidados», puedes especificarlos en tus reglas de validación usando la sintaxis de «punto»:
$request->validate([ 'title' => 'required|unique:posts|max:255', 'author.name' => 'required', 'author.description' => 'required', ]);
Mostrando los errores de validación
¿Qué sucede si los parámetros de solicitud entrantes no pasan las reglas de validación dadas? Cómo mencionamos anteriormente, Laravel redirigirá automáticamente al usuario a su ubicación previa. Además, todos los errores de validación serán automáticamente movidos instantáneamente a la sesión.
De nuevo, observa que no tuvimos que enlazar explícitamente los mensajes de error con la vista en nuestra ruta GET
. Esto es porque Laravel revisará los errores en la sesión de datos y los enlazará automáticamente a la vista si están disponibles. La variable $errors
será una instancia de Illuminate\Support\MessageBag
. Para mayor información sobre cómo trabajar con este objeto, revisa su documentación.
La variable $errors
es enlazada a la vista por el middleware Illuminate\View\Middleware\ShareErrorsFromSession
, el cual es proporcionado por el grupo de middleware web
. Cuando este middleware se aplique una variable $errors
siempre estará disponible en tus vistas, permitiendo que asumas convenientemente que la variable $errors
está definida siempre y puede ser usada con seguridad.
Así, en nuestro ejemplo, el usuario será redirigido al método create
de nuestro controlador cuando la validación falle, permitiéndonos mostrar los mensajes de error en la vista:
<!-- /resources/views/post/create.blade.php --> <h1>Create Post</h1> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <!-- Create Post Form -->
Directiva @error
También puedes usar la directiva @error
de Blade para rápidamente comprobar si los mensajes de error de validación existen para un atributo dado. Dentro de una directiva @error
, puedes mostrar la variable $message
para mostrar el mensaje de error:
<!-- /resources/views/post/create.blade.php --> <label for="title">Post Title</label> <input id="title" type="text" class="@error('title') is-invalid @enderror"> @error('title') <div class="alert alert-danger">{{ $message }}</div> @enderror
Una observación sobre los campos opcionales
De forma predeterminada, Laravel incluye los middleware TrimStrings
y ConvertEmptyStringsToNull
en la pila global de middleware de tu aplicación. Estos middleware son listados en la pila por la clase App\Http\Kernel
. Debido a esto, con frecuencia necesitarás marcar tus campos «opcionales» de solicitud como nullable
si no quieres que el validador considere los valores null
como no válidos. Por ejemplo:
$request->validate([ 'title' => 'required|unique:posts|max:255', 'body' => 'required', 'publish_at' => 'nullable|date', ]);
En este ejemplo, estamos especificando que el campo publish_at
puede que sea o null
o una representación de fecha válida. Si el modificador nullable
no es agregado a la definición de la regla, el validador consideraría el null
como una fecha no válida.
Solicitudes AJAX y validación
En este ejemplo, usamos un formulario tradicional para enviar datos a la aplicación. Sin embargo, muchas aplicaciones usan solicitudes AJAX. Al momento de usar el método validate
durante una solicitud AJAX, Laravel no generará una respuesta de redirección. En su lugar, Laravel genera una respuesta JSON que contiene todos los errores de validación. Esta respuesta JSON será enviada con un código de estado HTTP 422.
Validación de solicitud de formulario
Creando solicitudes de formulario (form request)
Para escenarios de validación más complejos, puede que desees crear una «solicitud de formulario (form request)». Las Form Request son clases de solicitud personalizadas que contienen la lógica de validación. Para crear una clase de Form Request, usa el comando de CLI de Artisan make:request
:
php artisan make:request StoreBlogPost
La clase generada será colocada en el directorio app/Http/Requests
. Si este directorio no existe, será creado cuando ejecutes el comando make:request
. Agreguemos unas cuantas reglas de validación al método rules
:
/** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; }
Puedes declarar el tipo de cualquier dependencia que necesites dentro de la firma del método rules
. Se resolverán automáticamente a través del contenedor de servicio de Laravel.
Así que, ¿Cómo son evaluadas las reglas de validación? Todo lo que necesitas hacer es poner la referencia de la solicitud en tu método de controlador. La Form Request entrante es validada antes de que el método de controlador sea ejecutado, lo que significa que no necesitas complicar tu controlador con ninguna lógica de validación:
/** * Store the incoming blog post. * * @param StoreBlogPost $request * @return Response */ public function store(StoreBlogPost $request) { // The incoming request is valid... // Retrieve the validated input data... $validated = $request->validated(); }
Si la validación falla, una respuesta de redirección será generada para enviar al usuario de vuelta a su ubicación previa. Los errores también serán movidos instantáneamente a la sesión de modo que estén disponibles para mostrarlos. Si la solicitud fuese una solicitud AJAX, una respuesta HTTP con un código de estado 422 será devuelta al usuario incluyendo una representación JSON de los errores de validación.
Agregando hooks posteriores a solicitudes de formularios
Si prefieres agregar un hook «posterior» a una Form Request, puedes usar el método withValidator
. Este método recibe el validador completamente construido, permitiendo que ejecutes cualquiera de sus métodos antes de que las reglas de validación sean evaluadas realmente:
/** * Configure the validator instance. * * @param \Illuminate\Validation\Validator $validator * @return void */ public function withValidator($validator) { $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); }
Autorizando solicitudes de formularios
La clase Form Request también contiene un método authorize
. Dentro de este método, puedes verificar si el usuario autenticado realmente tiene la autoridad para actualizar un recurso dado. Por ejemplo, puedes determinar si a un usuario le pertenece el comentario del blog que está intentando actualizar
/** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { $comment = Comment::find($this->route('comment')); return $comment && $this->user()->can('update', $comment); }
Dado que todas las form requests extienden de la clase solicitud base (Request) de Laravel, podemos usar el método user
para acceder al usuario actualmente autenticado. También observa la llamada al método route
en el ejemplo anterior. Este método te otorga acceso a los parámetros de URI definidos en la ruta que es ejecutada, tal como el parámetro {comment}
en el ejemplo siguiente:
Route::post('comment/{comment}');
Si el método authorize
devuelve false
, una respuesta HTTP con un código de estado 403 será devuelta automáticamente y tu método de controlador no se ejecutará.
Si planeas tener la lógica de autorización en otra parte de tu aplicación, devuelve true
desde el método authorize
:
/** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; }
Puedes declarar el tipo de cualquier dependencia que necesites dentro de la firma del método authorize
. Se resolverán automáticamente a través del contenedor de servicio de Laravel.
Personalizando los mensajes de error
Puedes personalizar los mensajes de error usados por el form request al sobrescribir el método messages
. Este método debería devolver un arreglo de pares atributo / regla y sus correspondientes mensajes de error:
/** * Get the error messages for the defined validation rules. * * @return array */ public function messages() { return [ 'title.required' => 'A title is required', 'body.required' => 'A message is required', ]; }
Personalizando los atributos de validación
Si desea que la parte :attribute
de tu mensaje de validación se reemplace con un nombre de atributo personalizado, puedes especificar los nombres personalizados sobrescribiendo el método attributes
. Este método debería devolver un arreglo de pares de atributo / nombre:
/** * Get custom attributes for validator errors. * * @return array */ public function attributes() { return [ 'email' => 'email address', ]; }
Preparar datos para validación
Si necesitas limpiar datos de la petición antes de aplicar tus reglas de validación, puedes usar el método prepareForValidation
:
use Illuminate\Support\Str; /** * Prepare the data for validation. * * @return void */ protected function prepareForValidation() { $this->merge([ 'slug' => Str::slug($this->slug), ]); }
Creando validadores manualmente
Si no quieres usar el método validate
en la solicitud, puedes crear una instancia de validador manualmente usando la clase facade Validator
. El método make
en la clase facade genera una nueva instancia del validador:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; class PostController extends Controller { /** * Store a new blog post. * * @param Request $request * @return Response */ public function store(Request $request) { $validator = Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); if ($validator->fails()) { return redirect('post/create') ->withErrors($validator) ->withInput(); } // Store the blog post... } }
El primer argumento pasado al método make
son los datos bajo validación. El segundo argumento son las reglas de validación que deberían ser aplicadas a los datos.
Después de verificar si la validación de solicitud falló, puedes usar el método withErrors
para mover instantáneamente los mensajes de error a la sesión. Al momento de usar este método, la variable $errors
será compartida automáticamente con tus vistas después de la redirección, permitiendo que los muestres de vuelta al usuario. El método withErrors
acepta un validador, un MessageBag
o un array
de PHP.
Redirección automática
Si prefieres crear manualmente una instancia del validador pero aún tomar ventaja de la redirección automática ofrecida por el método validate
de la solicitud, puedes ejecutar el método validate
en una instancia de validador existente. Si la validación falla, el usuario automáticamente será redirigido o, en el caso de una solicitud AJAX, le será devuelta una respuesta JSON:
Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ])->validate();
Paquetes de errores con nombres
Si tienes múltiples formularios en una sola página, puede que desees nombrar el MessageBag
de errores, permitiendo que obtengas los mensajes de error para un formulario específico. Pasa un nombre como segundo argumento a withErrors
:
return redirect('register') ->withErrors($validator, 'login');
Entonces puedes acceder a la instancia de MessageBag
nombrada desde la variable $errors
:
{{ $errors->login->first('email') }}
Hook de validación posterior
El validador también permite que adjuntes funciones de retorno (callbacks) para que sean ejecutadas después que se complete la validación. Esto permite que ejecutes fácilmente validación adicional e incluso agregar más mensajes de error a la colección de mensajes. Para empezar, usa el método after
en una instancia de validador:
$validator = Validator::make(...); $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); if ($validator->fails()) { // }
Trabajando con los mensajes de error
Después de ejecutar el método errors
en una instancia Validator
, recibirás una instancia Illuminate\Support\MessageBag
, la cual tiene una variedad de métodos convenientes para trabajar con los mensajes de error. La variable $errors
que se hace disponible automáticamente para todas las vistas también es una instancia de la clase MessageBag
.
Obteniendo el primer mensaje de error para un campo
Para obtener el primer mensaje de error para un campo dado, usa el método first
:
$errors = $validator->errors(); echo $errors->first('email');
Obteniendo todos los mensajes de error para un campo
Si necesitas obtener un arreglo de todos los mensajes para un campo dado, usa el método get
:
foreach ($errors->get('email') as $message) { // }
Si estás validando un campo de formulario de arreglo, puedes obtener todos los mensajes para cada uno de los elementos del arreglo usando el carácter *
:
foreach ($errors->get('attachments.*') as $message) { // }
Obteniendo todos los mensajes de error para todos los campos
Para obtener un arreglo de todos los mensajes para todos los campos, usa el método all
:
foreach ($errors->all() as $message) { // }
Determinando si existen mensajes para un campo
El método has
puede ser usado para determinar si existe algún mensaje de error para un campo dado:
if ($errors->has('email')) { // }
Mensajes de error personalizados
Si es necesario, puedes usar mensajes de error personalizados en vez de los predeterminados. Hay varias formas para especificar mensajes personalizados. Primero, puedes pasar los mensajes personalizados como tercer argumento al método Validator::make
:
$messages = [ 'required' => 'The :attribute field is required.', ]; $validator = Validator::make($input, $rules, $messages);
En este ejemplo, el marcador :attribute
será reemplazado por el nombre real del campo bajo validación. También puedes utilizar otros marcadores en mensajes de validación. Por ejemplo:
$messages = [ 'same' => 'The :attribute and :other must match.', 'size' => 'The :attribute must be exactly :size.', 'between' => 'The :attribute value :input is not between :min - :max.', 'in' => 'The :attribute must be one of the following types: :values', ];
Especificando un mensaje personalizado para un atributo dado
Algunas veces puedes querer especificar un mensaje de error personalizado sólo para un campo específico. Puedes hacer eso usando notación de «punto». Especifica el nombre del atributo al principio, seguido por la regla:
$messages = [ 'email.required' => 'We need to know your e-mail address!', ];
Especificando mensajes personalizados en archivos de idiomas
En muchos casos, probablemente especificarás tus mensajes personalizados en un archivo de idioma en lugar de pasarlos directamente al Validator
. Para hacer eso, agrega tus mensajes al arreglo custom
en el archivo de idioma resources/lang/xx/validation.php
:
'custom' => [ 'email' => [ 'required' => 'We need to know your e-mail address!', ], ],
Especificando los atributos personalizados en archivos de idiomas
Si prefieres que la porción :attribute
de tu mensaje de validación sea reemplazada con un nombre de atributo personalizado, puedes especificar el nombre personalizado en el arreglo attributes
de tu archivo de idioma resources/lang/xx/validation.php
:
'attributes' => [ 'email' => 'email address', ],
Especificando los valores personalizados en archivos de idiomas
A veces es posible que necesites que la parte :value
de tu mensaje de validación sea reemplazada por una representación personalizada del valor. Por ejemplo, considera la siguiente regla que especifica que se requiere un número de tarjeta de crédito si el payment_type
tiene un valor de cc
:
$request->validate([ 'credit_card_number' => 'required_if:payment_type,cc' ]);
Si esta regla de validación falla, producirá el siguiente mensaje de error:
The credit card number field is required when payment type is cc.
En lugar de mostrar cc
como el valor del tipo de pago, puedes especificar una representación de valor personalizada en tu archivo de idioma validation
definiendo un arreglo values
:
'values' => [ 'payment_type' => [ 'cc' => 'credit card' ], ],
Ahora, si la regla de validación falla, producirá el siguiente mensaje:
The credit card number field is required when payment type is credit card.
Reglas de validación disponibles
A continuación se muestra una lista con todas las reglas de validación disponibles y su función:
Accepted
Active URL
After (Date)
After Or Equal (Date)
Alpha
Alpha Dash
Alpha Numeric
Array
Bail
Before (Date)
Before Or Equal (Date)
Between
Boolean
Confirmed
Date
Date Equals
Date Format
Different
Digits
Digits Between
Dimensions (Image Files)
Distinct
E-Mail
Ends With
Exclude If
Exclude Unless
Exists (Database)
File
Filled
Greater Than
Greater Than Or Equal
Image (File)
In
In Array
Integer
IP Address
JSON
Less Than
Less Than Or Equal
Max
MIME Types
MIME Type By File Extension
Min
Not In
Not Regex
Nullable
Numeric
Password
Present
Regular Expression
Required
Required If
Required Unless
Required With
Required With All
Required Without
Required Without All
Same
Size
Sometimes
Starts With
String
Timezone
Unique (Database)
URL
UUID
accepted
El campo bajo validación debe ser yes, on, 1, o true. Esto es útil para validar la aceptación de «Términos de Servicio», por ejemplo.
active_url
El campo bajo validación debe tener un registro A o AAAA válido de acuerdo a la función de PHP dns_get_record
. El hostname de la URL proporcionada es extraído usando la función de PHP parse_url
antes de ser pasado a dns_get_record
.
after:date
El campo bajo validación debe ser un valor después de una fecha dada. Las fechas serán pasadas a la función de PHP strtotime
:
'start_date' => 'required|date|after:tomorrow'
En lugar de pasar una cadena de fecha para que sea evaluada por strtotime
, puedes especificar otro campo para comparar con la fecha:
'finish_date' => 'required|date|after:start_date'
after_or_equal:date
El campo bajo validación debe ser un valor después o igual a la fecha dada. Para mayor información, observa la regla after.
alpha
El campo bajo validación debe estar compuesto completamente por caracteres alfabéticos.
alpha_dash
El campo bajo validación puede tener caracteres alfanuméricos, al igual que guiones cortos y guiones largos.
alpha_num
El campo bajo validación debe estar compuesto completamente por caracteres alfanuméricos.
array
El campo bajo validación debe ser un array
de PHP.
bail
Detiene la ejecución de las reglas de validación después del primer error de validación.
before:date
El campo bajo validación debe ser un valor que preceda la fecha dada. Las fechas serán pasadas a la función PHP strtotime
. Además, como la regla after
, el nombre de otro campo bajo validación puede suministrarse como el valor de fecha date
.
before_or_equal:date
Este campo bajo validación debe ser un valor que preceda o igual a la fecha dada. Las fechas serán pasadas a la función de PHP strtotime
. Además, como la regla after
, el nombre de otro campo bajo validación puede suministrarse como el valor de fecha date
.
between:min,max
El campo bajo validación debe tener un tamaño entre el min y max dado. Las cadenas, los números, los arreglos y los archivos se evalúan de la misma manera que la regla size
.
boolean
El campo bajo validación debe poder ser convertido como un booleano. Las entrada aceptadas son true
, false
, 1
, 0
, "1"
y "0"
.
confirmed
El campo bajo validación debe tener un campo que coincida con foo_confirmation
. Por ejemplo, si el campo bajo validación es password
, un campo password_confirmation
que coincida debe estar presente en la entrada.
date
El campo bajo validación debe ser una fecha válida, no relativa, de acuerdo a la función de PHP strtotime
.
date_equals:date
El campo bajo validación debe ser igual a la fecha dada. Las fechas serán pasadas a la función de PHP strtotime
.
date_format:format
El campo bajo validación debe coincidir con el formato format dado. Deberías usar date
o date_format
al momento de validar un campo, no ambos. Esta regla de validación es compatible con todos los formatos compatibles con la clase DateTime de PHP.
different:field
El campo bajo validación debe tener un valor distinto de field.
digits:value
El campo bajo validación debe ser de tipo numérico y debe tener una longitud exacta de value.
digits_between:min,max
El campo bajo validación debe ser numérico y tener una longitud entre los valores de min y max dados.
dimensions
El archivo bajo validación debe ser una imagen que cumpla con las restricciones de dimensión especificadas por los parámetros de la regla:
'avatar' => 'dimensions:min_width=100,min_height=200'
Las restricciones disponibles son: min_width, max_width, min_height, max_height, width, height, ratio.
Una restricción ratio debería ser representada como el ancho dividido por la altura. Esto puede ser especificado por una instrucción como 3/2
o en decimal como 1.5
:
'avatar' => 'dimensions:ratio=3/2'
Dado que esta regla requiere varios argumentos, puedes usar el método Rule::dimensions
para construir con fluidez la regla:
use Illuminate\Validation\Rule; Validator::make($data, [ 'avatar' => [ 'required', Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2), ], ]);
distinct
Al momento de trabajar con arreglos, el campo bajo validación no debe tener ningún valor duplicado.
'foo.*.id' => 'distinct'
El campo bajo validación debe estar formateado como una dirección de correo electrónico. Esta validación hace uso del paquete egulias/email-validator para validar la dirección de correo electrónico. Por defecto, el validador RFCValidation
es aplicado, pero también puedes aplicar otros estilos de validación:
'email' => 'email:rfc,dns'
El ejemplo anterior aplicará las validaciones RFCValidation
y DNSCheckValidation
. Aquí está una lista de los estilos de validación que puedes aplicar:
rfc
:RFCValidation
strict
:NoRFCWarningsValidation
dns
:DNSCheckValidation
spoof
:SpoofCheckValidation
filter
:FilterEmailValidation
El validador filter
, que hace uso de la función filter_var
de PHP, se entrega con Laravel y es un comportamiento anterior a Laravel 5.8. Los validadores dns
y spoof
requieren la extensión intl
de PHP.
ends_with:foo,bar,…
El campo bajo validación debe terminar con alguno de los valores dados.
exclude_if:anotherfield,value
El campo bajo validación será excluido de los datos de la petición retornados por los métodos validate
y validated
si el campo anotherfield es igual al valor value.
exclude_unless:anotherfield,value
El campo bajo validación será excluido de los datos de la petición retornados por los métodos validate
y validated
a menos que anotherfield sea igual a value.
exists:table,column
El campo bajo validación debe existir en una tabla de base de datos dada.
Uso Básico de la Regla Exists
'state' => 'exists:states'
Si la opción column
no está especificada, se usará el nombre del campo.
Especificando un Nombre de Columna Personalizado
'state' => 'exists:states,abbreviation'
Ocasionalmente, puedes necesitar especificar una conexión de base de datos para que sea usada por la consulta exists
. Puedes lograr esto anteponiendo el nombre de la conexión al nombre de la tabla, usando la sintaxis de «punto»:
'email' => 'exists:connection.staff,email'
En lugar de especificar el nombre de la tabla directamente, puedes especificar el modelo de Eloquent que debe ser usado para determinar el nombre de la tabla:
'user_id' => 'exists:App\User,id'
Si prefieres personalizar la consulta ejecutada por la regla de validación, puedes usar la clase Rule
para definir con fluidez la regla. En este ejemplo, también especificaremos las reglas de validación como un arreglo en vez de usar el carácter |
para delimitarlas:
use Illuminate\Validation\Rule; Validator::make($data, [ 'email' => [ 'required', Rule::exists('staff')->where(function ($query) { $query->where('account_id', 1); }), ], ]);
file
El campo bajo validación debe ser un archivo que sea cargado exitosamente.
filled
El campo bajo validación no debe estar vacío cuando esté presente.
gt:field
El campo bajo validación debe ser mayor que el campo field dado. Los dos campos deben ser del mismo tipo. Las cadenas, los números, los arreglos y los archivos se evalúan utilizando las mismas convenciones que la regla size
.
gte:field
El campo bajo validación debe ser mayor o igual que el campo field dado. Los dos campos deben ser del mismo tipo. Las cadenas, los números, los arreglos y los archivos se evalúan utilizando las mismas convenciones que la regla size
.
image
El archivo bajo validación debe ser una imagen (jpeg, png, bmp, gif, svg o webp)
in:foo,bar,…
El archivo bajo validación debe estar incluido en la lista dada de valores. Debido a que esta regla requiere con frecuencia que hagas implode
a un arreglo, el método Rule::in
puede ser usado para construir fluidamente la regla:
use Illuminate\Validation\Rule; Validator::make($data, [ 'zones' => [ 'required', Rule::in(['first-zone', 'second-zone']), ], ]);
in_array:anotherfield.*
El campo bajo validación debe existir en los valores de otro campo dado por los valores de anotherfield.
integer
El campo bajo validación debe ser un entero.
Esta regla de validación no verifica que el campo sea del tipo de variable «entero», sólo que el campo sea una cadena o valor numérico que contenga un entero.
ip
El campo bajo validación debe ser una dirección IP.
ipv4
El campo bajo validación debe ser una dirección IPv4.
ipv6
El campo bajo validación debe ser una dirección IPv6.
json
El campo bajo validación debe ser una cadena JSON válida.
lt:field
El campo bajo validación debe ser menor que el valor dado por el campo field. Los dos campos deben ser del mismo tipo. Las cadenas, los números, los arreglos y los archivos se evalúan utilizando las mismas convenciones que la regla size
.
lte:field
El campo bajo validación debe ser menor o igual que el valor dado por el campo field. Los dos campos deben ser del mismo tipo. Las cadenas, los números, los arreglos y los archivos se evalúan utilizando las mismas convenciones que la regla size
.
max:value
El campo bajo validación debe ser menor que o igual a un valor máximo dado por value. Las cadenas, los números, los arreglos y los archivos son evaluados de la misma forma como la regla size
.
mimetypes:text/plain,…
El archivo bajo validación debe coincidir con uno de los tipos MIME dados:
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
Para determinar el tipo MIME del archivo cargado, el contenido del archivo será leído y el framework intentará suponer el tipo MIME, el cual puede ser distinto del tipo MIME proporcionado por el cliente.
mimes:foo,bar,…
El archivo bajo validación debe tener un tipo MIME correspondiente a uno con las extensiones listadas.
Uso Básico de la Regla MIME
'photo' => 'mimes:jpeg,bmp,png'
Incluso aunque solamente necesites especificar las extensiones, en realidad esta regla valida contra el tipo MIME del archivo, mediante la lectura del contenido del archivo y adivinando su tipo MIME.
Una lista completa de tipos MIME y sus correspondientes extensiones puede ser encontrada en la siguiente ubicación: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
min:value
El campo bajo validación deben tener un valor mínimo dado por value. Las cadenas, los números, los arreglos y los archivos son evaluados en la misma forma como la regla size
.
not_in:foo,bar,…
El campo bajo validación no debe estar incluido en la lista dada de valores. El método Rule::notIn
puede ser usado para construir fluidamente la regla:
use Illuminate\Validation\Rule; Validator::make($data, [ 'toppings' => [ 'required', Rule::notIn(['sprinkles', 'cherries']), ], ]);
not_regex:pattern
El campo bajo validación no debe coincidir con la expresión regular dada.
Internamente, esta regla usa la función PHP preg_match
. El patrón especificado debe obedecer el mismo formato requerido por preg_match
y, por lo tanto, también incluir delimitadores válidos. Por ejemplo: 'email' => 'not_regex:/^.+$/i'
.
Nota: Al usar los patrones regex
/ not_regex
, puede ser necesario especificar reglas en un arreglo en lugar de usar delimitadores de tubería o «pipes», especialmente si la expresión regular contiene un carácter pipe |
.
nullable
El campo bajo validación puede ser null
. Esto es particularmente útil al momento de validar tipos primitivos tales como cadenas y enteros que pueden contener valores null
.
numeric
El campo bajo validación debe ser de tipo numérico.
password
El campo bajo validación debe coincidir con la contraseña del usuario autenticado. Puedes especificar un guard de autenticación utilizando el primer parámetro de la regla:
'password' => 'password:api'
present
El campo bajo validación debe estar presente en los datos de entrada pero puede estar vacío.
regex:pattern
El campo bajo validación debe coincidir con la expresión regular dada.
Internamente, esta regla usa la función PHP preg_match
. El patrón especificado debe obedecer el mismo formato requerido por preg_match
y, por lo tanto, también incluir delimitadores válidos. Por ejemplo: 'email' => 'regex:/^.+@.+$/i'
.
Nota: Al usar los patrones regex
/ not_regex
, puede ser necesario especificar reglas en un arreglo en lugar de usar delimitadores de tubería o «pipes», especialmente si la expresión regular contiene un carácter pipe |
.
required
El campo bajo validación debe estar presente entre los datos entrada y no estar vacío. Un campo es considerado «vacío» si alguna de las siguientes condiciones es cierta:
- El valor es
null
. - El valor es una cadena vacía.
- El valor es un arreglo vacío o un objeto
Countable
vacío. - El valor es un archivo cargado sin ruta.
required_if:anotherfield,value,…
El campo bajo validación debe estar presente y no vacío si el campo anotherfield es igual a cualquier valor dado por value.
Si deseas construir una condición más compleja para la regla required_if
, puedes usar el método Rule::requiredIf
. Este método acepta un valor booleano o un Closure. Cuando se pasa un Closure, éste debe devolver true
o false
para indicar si el campo bajo validación es obligatorio:
use Illuminate\Validation\Rule; Validator::make($request->all(), [ 'role_id' => Rule::requiredIf($request->user()->is_admin), ]); Validator::make($request->all(), [ 'role_id' => Rule::requiredIf(function () use ($request) { return $request->user()->is_admin; }), ]);
required_unless:anotherfield,value,…
El campo bajo validación debe estar presente y no vacío a menos que el campo anotherfield sea igual a cualquier valor dado por value.
required_with:foo,bar,…
El campo bajo validación debe estar presente y no vacío solamente si cualquiera de los otros campos especificados están presentes.
required_with_all:foo,bar,…
El campo bajo validación debe estar presente y no vacío solamente si todos los otros campos especificados están presentes.
required_without:foo,bar,…
El campo bajo validación debe estar presente y no vacío solamente cuando cualquiera de los otros campos especificados no están presentes.
required_without_all:foo,bar,…
El campo bajo validación debe estar presente y no vacío solamente cuando todos los demás campos especificados no están presentes.
same:field
El campo dado por field debe coincidir con el campo bajo validación.
size:value
El campo bajo validación debe tener un tamaño que coincida con el valor value dado. Para datos de cadena, el valor value corresponde al número de caracteres. Para datos numéricos, el valor value corresponde a un valor entero dado (el atributo debe tener también la regla numeric
o integer
). Para un arreglo, el valor size corresponde con el count
del arreglo. Para archivos, el valor de size corresponde al tamaño del archivo en kilobytes. Vamos a observar algunos ejemplos:
// Validate that a string is exactly 12 characters long... 'title' => 'size:12'; // Validate that a provided integer equals 10... 'seats' => 'integer|size:10'; // Validate that an array has exactly 5 elements... 'tags' => 'array|size:5'; // Validate that an uploaded file is exactly 512 kilobytes... 'image' => 'file|size:512';
starts_with:foo,bar,…
El campo bajo validación debe comenzar con uno de los valores dados.
string
El campo bajo validación debe ser una cadena. Si prefieres permitir que el campo también sea null
, deberías asignar la regla nullable
al campo.
timezone
El campo bajo validación debe ser un identificador de zona horaria válida de acuerdo con la función de PHP timezone_identifiers_list
.
unique:table,column,except,idColumn
El campo bajo validación no debe existir dentro de la tabla de base de datos dada.
Especificando un nombre de tabla o columna personalizado:
En lugar de especificar el nombre de la tabla directamente, puedes especificar el modelo de Eloquent que debe ser usado para determinar el nombre de la tabla:
'email' => 'unique:App\User,email_address'
La opción column
puede ser usada para especificar la columna correspondiente al campo en la base de datos. Si la opción column
no es especificada, el nombre del campo será usado.
'email' => 'unique:users,email_address'
Conexión de base de datos personalizada
Ocasionalmente, puedes necesitar establecer una conexión personalizada para las consultas de bases de datos hechas por el validador. Como has visto anteriormente, al establecer unique:users
como una regla de validación usará la conexión de base de datos predeterminada en la consulta de base de datos. Para sobrescribir esto, especifica la conexión y el nombre de la tabla usando la sintaxis de «punto»:
'email' => 'unique:connection.users,email_address'
Forzando una regla unique para ignorar un ID dado:
Algunas veces, puedes desear ignorar un ID dado durante la verificación de unicidad. Por ejemplo, considera una pantalla «update profile» que incluya el nombre del usuario, dirección de correo electrónico y ubicación. Posiblemente, querrás verificar que la dirección de correo electrónico es única. Sin embargo, si el usuario solamente cambia el campo nombre y no el campo con el correo electrónico, no quieres que un error de validación sea lanzado porque el usuario ya es el propietario de la dirección de correo electrónico.
Para instruir al validador para que ignore el ID del usuario, usaremos la clase Rule
para definir fluidamente la regla. En este ejemplo, también especificaremos las reglas de validación como un arreglo en lugar de usar el carácter |
para delimitar las reglas:
use Illuminate\Validation\Rule; Validator::make($data, [ 'email' => [ 'required', Rule::unique('users')->ignore($user->id), ], ]);
Nunca debes pasar ningún input de la solicitud controlado por cualquier usuario en el método ignore
. En su lugar, sólo debes pasar un ID único generado por el sistema, como un ID autoincremental o UUID de una instancia de modelo Eloquent. De lo contrario, tu aplicación será vulnerable a un ataque de inyección SQL.
En lugar de pasar el valor de la clave del modelo al método ignore
, puedes pasar la instancia completa del modelo. Laravel automáticamente extraerá la clave del modelo:
Rule::unique('users')->ignore($user)
Si tu tabla usa un nombre de columna de clave primaria distinto de id
, puedes especificar el nombre de la columna al momento de llamar al método ignore
:
Rule::unique('users')->ignore($user->id, 'user_id')
Por defecto, la regla única
verificará la unicidad de la columna que coincide con el nombre del atributo que se valida. Sin embargo, puedes pasar un nombre de columna diferente como segundo argumento al método unique
:
Rule::unique('users', 'email_address')->ignore($user->id),
Agregando cláusulas where adicionales:
También puedes especificar restricciones de consultas adicionales personalizando la consulta mediante el método where
. Por ejemplo, agreguemos una restricción que verifique que el account_id
es 1
:
'email' => Rule::unique('users')->where(function ($query) { return $query->where('account_id', 1); })
url
El campo bajo validación debe ser una URL válida.
uuid
El campo bajo validación debe ser un identificador único universal (UUID) válido acorde con la RFC 4122 (versión 1, 3, 4 o 5).
Agregando reglas condicionalmente
Validando sólo cuando un campo esté presente
En algunas situaciones, puedes desear ejecutar la verificación contra un campo solamente si ese campo está presente en el arreglo de campos. Para conseguir esto rápidamente, agrega la regla sometimes
en tu lista:
$v = Validator::make($data, [ 'email' => 'sometimes|required|email', ]);
En el ejemplo anterior, el campo email
solamente será validado si está presente en el arreglo $data
.
Si estás intentando validar un campo que siempre deba estar presente pero puede estar vacío, revisa esta nota sobre campos opcionales
Validación condicional compleja
Algunas veces puedes desear agregar reglas de validación basadas en lógica condicional más compleja. Por ejemplo, puedes desear solicitar un campo dado solamente si otro campo tiene un valor mayor que 100. O, puedes necesitar que dos campos tengan un valor dado solamente cuando otro campo esté presente. Agregar estas reglas de validación no tiene que ser un dolor. Primero, crea una instancia Validator
con tus reglas estáticas que nunca cambian:
$v = Validator::make($data, [ 'email' => 'required|email', 'games' => 'required|numeric', ]);
Asumamos que nuestra aplicación web es sobre coleccionistas de juegos. Si un coleccionista de juego se registra con nuestra aplicación y posee más de 100 juegos, queremos que explique porqué posee tantos juegos. Por ejemplo, quizá administre una tienda de reventa de juegos, o puede ser que solo disfrute coleccionar. Para agregar este requerimiento condicionalmente, podemos usar el método sometimes
en la instancia Validator
:
$v->sometimes('reason', 'required|max:500', function ($input) { return $input->games >= 100; });
El primer argumento pasado al método sometimes
es el nombre del campo que estamos validando condicionalmente. El segundo argumento son las reglas que queremos agregar. Si la Closure
pasada como tercer argumento devuelve true
, las reglas serán agregadas. Este método hace que sea muy fácil construir validaciones condicionales complejas. Incluso puedes agregar validaciones condicionales para varios campos de una sola vez:
$v->sometimes(['reason', 'cost'], 'required', function ($input) { return $input->games >= 100; });
El parámetro $input
pasado a tu Closure
será una instancia de Illuminate\Support\Fluent
y puede ser usado para acceder a tus campos y archivos.
Validando arreglos
Validar arreglos basados en campos de entrada de formulario no tiene que ser un dolor. Puedes usar la «notación de punto» para validar atributos dentro de un arreglo. Por ejemplo, si la solicitud HTTP entrante contiene un campo photos[profile]
, puedes validarlo así:
$validator = Validator::make($request->all(), [ 'photos.profile' => 'required|image', ]);
También puedes validar cada elemento de un arreglo. Por ejemplo, para validar que cada dirección electrónica en un campo de entrada de arreglo sea único, puedes hacer lo siguiente:
$validator = Validator::make($request->all(), [ 'person.*.email' => 'email|unique:users', 'person.*.first_name' => 'required_with:person.*.last_name', ]);
De igual forma, puedes usar el carácter *
al momento de especificar tus mensajes de validación en tus archivos de idiomas, haciendo que sea muy fácil usar un único mensaje de validación para campos basados en arreglos:
'custom' => [ 'person.*.email' => [ 'unique' => 'Each person must have a unique e-mail address', ] ],
Reglas de validación personalizadas
Usando objetos de reglas
Laravel proporciona una variedad de reglas de validación útiles; sin embargo, puedes desear especificar algunas propias. Un método para registrar reglas de validación personalizadas es usar objetos de regla. Para generar un nuevo objeto de regla, puedes usar el comando Artisan make:rule
. Usemos este comando para generar una regla que verifique que una cadena esté en mayúscula. Laravel colocará la nueva regla en el directorio app/Rules
:
php artisan make:rule Uppercase
Una vez que la regla haya sido creada, estaremos listos para definir su comportamiento. Un objeto de regla contiene dos métodos: passes
y message
. El método passes
recibe el nombre y valor del atributo, y debería devolver true
o false
dependiendo de si el valor de atributo es válido o no. El método message
debería devolver el mensaje de error de validación que debería ser usado cuando la validación falle:
<?php namespace App\Rules; use Illuminate\Contracts\Validation\Rule; class Uppercase implements Rule { /** * Determine if the validation rule passes. * * @param string $attribute * @param mixed $value * @return bool */ public function passes($attribute, $value) { return strtoupper($value) === $value; } /** * Get the validation error message. * * @return string */ public function message() { return 'The :attribute must be uppercase.'; } }
Por supuesto, puedes ejecutar el helper trans
de tu método message
si prefieres devolver un mensaje de error de tus archivos de traducción:
/** * Get the validation error message. * * @return string */ public function message() { return trans('validation.uppercase'); }
Una vez que la regla haya sido definida, puedes adjuntarla a un validador al pasar una instancia del objeto de regla con tus otras reglas de validación:
use App\Rules\Uppercase; $request->validate([ 'name' => ['required', 'string', new Uppercase], ]);
Usando closures
Si solo necesitas la funcionalidad de una regla personalizada una vez a lo largo de tu aplicación, puedes usar un Closure en lugar de un objeto de regla. El Closure recibe el nombre del atributo, el valor del atributo y una llamada de retorno (callback) $fail
que se debe llamar si falla la validación:
$validator = Validator::make($request->all(), [ 'title' => [ 'required', 'max:255', function ($attribute, $value, $fail) { if ($value === 'foo') { $fail($attribute.' is invalid.'); } }, ], ]);
Usando extensiones
Otro método para registrar reglas de validación personalizadas es usar el método extend
en la clase facade Validator
. Usemos este método dentro de un proveedor de servicio para registrar una regla de validación personalizada:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Validator; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // } /** * Bootstrap any application services. * * @return void */ public function boot() { Validator::extend('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; }); } }
La Closure del validador personalizada recibe cuatro argumentos: el nombre del atributo $attribute
que está siendo validado, el valor $value
del atributo, un arreglo de parámetros $parameters
pasado a la regla y la instancia Validator
.
También puedes pasar una clase y método al método extend
en vez de una Closure:
Validator::extend('foo', 'FooValidator@validate');
Definiendo el mensaje de error
También necesitarás definir un mensaje de error para tu regla personalizada. Puedes hacer eso usando un arreglo de mensajes personalizados en línea o agregando una entrada en el archivo de idioma de validación. Este mensaje debería ser colocado en el primer nivel del arreglo, no dentro del arreglo custom
, el cual es solamente para mensajes de error específicos de atributos:
"foo" => "Your input was invalid!", "accepted" => "The :attribute must be accepted.", // The rest of the validation error messages...
Al momento de crear una regla de validación personalizada, algunas veces puedes necesitar definir reemplazos de marcadores personalizados para los mensajes de error. Puedes hacerlo creando un Validador personalizado como se describió anteriormente, y luego haciendo una llamada al método replacer
en la clase facade Validator
. Puedes hacer esto dentro del método boot
de un proveedor de servicio:
/** * Bootstrap any application services. * * @return void */ public function boot() { Validator::extend(...); Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) { return str_replace(...); }); }
Extensiones implícitas
De forma predeterminada, cuando un atributo que está siendo validado no está presente o contiene una cadena vacía, las reglas de validación normales, incluyendo las extensiones personalizadas, no son ejecutadas. Por ejemplo, la regla unique
no será ejecutada en una cadena vacía:
$rules = ['name' => 'unique:users,name']; $input = ['name' => '']; Validator::make($input, $rules)->passes(); // true
Para que una regla se ejecute incluso cuando un atributo esté vacío, la regla debe implicar que el atributo sea obligatorio. Para crear tal extensión «implícita», usa el método Validator::extendImplicit()
:
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; });
Una extensión «implícita» solamente implica que el atributo es obligatorio. Si esto realmente invalida un atributo vacío o faltante depende de ti.
Reglas de objetos implícitas
Si te gustaría que una regla de objeto se ejecute cuando un atributo está vacío, debes implementar la interfaz Illuminate\Contracts\Validation\ImplicitRule
. Esta interfaz funciona como una «interfaz marcador» para el validador; por lo tanto, no contiene ningún método que necesites implementar.
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.
Lección anterior Sesión HTTP - Documentación de Laravel 6 Lección siguiente Manejo de Errores - Documentación de Laravel 6