1. Conceptos básicos
  2. Validación

Introducción

Laravel proporciona varios enfoques diferentes para validar los datos entrantes de tu aplicación. Es más común usar el método validate disponible en todas las solicitudes HTTP entrantes. Sin embargo, también discutiremos otros enfoques para la validación.

Laravel incluye una amplia variedad de prácticas reglas de validación que puedes aplicar a los datos, incluso brindando la capacidad de validar si los valores son únicos en una tabla de base de datos determinada. Cubriremos cada una de estas reglas de validación en detalle para que estés familiarizado con todas las características de validación de Laravel.

Inicio rápido de validación

Para conocer las potentes características de validación de Laravel, veamos un ejemplo completo de cómo validar un formulario y mostrar los mensajes de error al usuario. Al leer este resumen de alto nivel, podrás obtener una buena comprensión general de cómo validar los datos de la solicitud entrante utilizando Laravel:

Definición de las rutas

Primero, supongamos que tenemos las siguientes rutas definidas en nuestro archivo routes/web.php:

use App\Http\Controllers\PostController;
 
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);

La ruta GET mostrará un formulario para que el usuario cree una nueva publicación en el blog, mientras que la ruta POST almacenará la nueva publicación en la base de datos.

Creación del controlador

A continuación, echemos un vistazo a un controlador simple que maneja las solicitudes entrantes a estas rutas. Dejaremos el método store vacío por ahora:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
 
class PostController extends Controller
{
/**
* Mostrar el formulario para crear una nueva entrada de blog.
*/
public function create(): View
{
return view('post.create');
}
 
/**
* Almacenar una nueva entrada de blog.
*/
public function store(Request $request): RedirectResponse
{
// Validar y almacenar la entrada del blog...
 
$post = /** ... */
 
return to_route('post.show', ['post' => $post->id]);
}
}

Escritura de la lógica de validación

Ahora estamos listos para completar nuestro método store con la lógica para validar la nueva entrada de blog. Para hacer esto, utilizaremos el método validate proporcionado por el objeto Illuminate\Http\Request. Si las reglas de validación se cumplen, tu código seguirá ejecutándose normalmente; sin embargo, si la validación falla, se lanzará una excepción Illuminate\Validation\ValidationException y la respuesta de error adecuada se enviará automáticamente al usuario.

Si la validación falla durante una solicitud HTTP tradicional, se generará una respuesta de redirección a la URL anterior. Si la solicitud entrante es una solicitud XHR, se devolverá una respuesta JSON que contiene los mensajes de error de validación.

Para tener una mejor comprensión del método validate, volvamos al método store:

/**
* Almacenar una nueva entrada de blog.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
 
// La entrada del blog es válida...
 
return redirect('/posts');
}

Como puedes ver, las reglas de validación se pasan al método validate. No te preocupes; todas las reglas de validación disponibles están documentadas. Nuevamente, si la validación falla, se generará automáticamente la respuesta adecuada. Si la validación pasa, nuestro controlador continuará ejecutándose normalmente.

Alternativamente, las reglas de validación se pueden especificar como arrays de reglas en lugar de una sola cadena delimitada por |:

$validatedData = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);

Además, puedes usar el método validateWithBag para validar una solicitud y almacenar cualquier mensaje de error dentro de una bolsa de errores nombrada:

$validatedData = $request->validateWithBag('post', [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);

Detener en el primer fallo de validación

A veces puedes desear dejar de ejecutar reglas de validación en un atributo después del primer fallo de validación. Para hacerlo, asigna la regla bail al atributo:

$request->validate([
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);

En este ejemplo, si la regla unique en el atributo title falla, la regla max no se comprobará. Las reglas se validarán en el orden en que se asignen.

Nota sobre atributos anidados

Si la solicitud HTTP entrante contiene datos de campo "anidados", puedes especificar estos campos en tus reglas de validación utilizando la sintaxis de "punto":

$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);

Por otro lado, si el nombre de tu campo contiene un período literal, puedes evitar explícitamente que se interprete como una sintaxis de "punto" escapando el período con una barra invertida:

$request->validate([
'title' => 'required|unique:posts|max:255',
'v1\.0' => 'required',
]);

Visualización de los errores de validación

Entonces, ¿qué sucede si los campos de la solicitud entrante no superan las reglas de validación dadas? Como se mencionó anteriormente, Laravel redirigirá automáticamente al usuario a su ubicación anterior. Además, todos los errores de validación y datos de entrada de la solicitud se almacenarán automáticamente en la sesión.

Se comparte una variable $errors con todas las vistas de tu aplicación mediante el middleware Illuminate\View\Middleware\ShareErrorsFromSession, que es proporcionado por el grupo de middleware web. Cuando se aplica este middleware, una variable $errors siempre estará disponible en tus vistas, lo que te permite asumir de manera conveniente que la variable $errors siempre está definida y se puede utilizar de manera segura. La variable $errors será una instancia de Illuminate\Support\MessageBag. Para obtener más información sobre cómo trabajar con este objeto, consulta su documentación.

Así que, en nuestro ejemplo, el usuario será redirigido al método create de nuestro controlador cuando la validación falle, lo que nos permite 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 -->

Personalización de los mensajes de error

Las reglas de validación integradas de Laravel tienen un mensaje de error que se encuentra en el archivo lang/en/validation.php de tu aplicación. Si tu aplicación no tiene un directorio lang, puedes indicar a Laravel que lo cree usando el comando Artisan lang:publish.

Dentro del archivo lang/en/validation.php, encontrarás una entrada de traducción para cada regla de validación. Eres libre de cambiar o modificar estos mensajes según las necesidades de tu aplicación.

Además, puedes copiar este archivo a otro directorio de idioma para traducir los mensajes al idioma de tu aplicación. Para obtener más información sobre la localización en Laravel, consulta la documentación completa de localización.

Advertencia Por defecto, el esqueleto de la aplicación Laravel no incluye el directorio lang. Si deseas personalizar los archivos de idioma de Laravel, puedes publicarlos mediante el comando Artisan lang:publish.

Solicitudes XHR y validación

En este ejemplo, usamos un formulario tradicional para enviar datos a la aplicación. Sin embargo, muchas aplicaciones reciben solicitudes XHR desde un frontend impulsado por JavaScript. Cuando usas el método validate durante una solicitud XHR, Laravel no generará una respuesta de redirección. En su lugar, Laravel generará una respuesta JSON que contiene todos los errores de validación. Esta respuesta JSON se enviará con un código de estado HTTP 422.

La directiva @error

Puedes usar la directiva Blade @error para determinar rápidamente si existen mensajes de error de validación para un atributo dado. Dentro de una directiva @error, puedes imprimir 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"
name="title"
class="@error('title') is-invalid @enderror">
 
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror

Si estás utilizando bolsas de errores con nombre, puedes pasar el nombre de la bolsa de errores como segundo argumento a la directiva @error:

<input ... class="@error('title', 'post') is-invalid @enderror">

Relleno de formularios

Cuando Laravel genera una respuesta de redirección debido a un error de validación, el framework flash automáticamente todos los datos de entrada de la solicitud a la sesión. Esto se hace para que puedas acceder cómodamente a la entrada durante la próxima solicitud y volver a completar el formulario que el usuario intentó enviar.

Para recuperar la entrada flash de la solicitud anterior, invoca el método old en una instancia de Illuminate\Http\Request. El método old recuperará los datos de entrada flash de la sesión:

$title = $request->old('title');

Laravel también proporciona un ayudante global old. Si estás mostrando la entrada antigua dentro de una plantilla Blade, es más conveniente usar el ayudante old para volver a completar el formulario. Si no hay una entrada antigua para el campo dado, se devolverá null:

<input type="text" name="title" value="{{ old('title') }}">

Nota sobre campos opcionales

De forma predeterminada, Laravel incluye los middleware TrimStrings y ConvertEmptyStringsToNull en la pila global de middleware de tu aplicación. Estos middleware se enumeran en la pila mediante la clase App\Http\Kernel. Debido a esto, a menudo necesitarás marcar tus campos de solicitud "opcionales" como nullable si no deseas 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 ser null o una representación de fecha válida. Si no se agrega el modificador nullable a la definición de la regla, el validador consideraría null como una fecha no válida.

Formato de respuesta de error de validación

Cuando tu aplicación genera una excepción Illuminate\Validation\ValidationException y la solicitud HTTP entrante espera una respuesta JSON, Laravel formateará automáticamente los mensajes de error para ti y devolverá una respuesta HTTP 422 Unprocessable Entity.

A continuación, puedes revisar un ejemplo del formato de respuesta JSON para errores de validación. Ten en cuenta que las claves de error anidadas se aplanan en formato de notación "punto":

{
"message": "The team name must be a string. (and 4 more errors)",
"errors": {
"team_name": [
"The team name must be a string.",
"The team name must be at least 1 characters."
],
"authorization.role": [
"The selected authorization.role is invalid."
],
"users.0.email": [
"The users.0.email field is required."
],
"users.2.email": [
"The users.2.email must be a valid email address."
]
}
}

Validación de solicitudes de formulario

Creación de solicitudes de formulario

Para escenarios de validación más complejos, es posible que desees crear una "solicitud de formulario" (form request). Las solicitudes de formulario son clases de solicitud personalizadas que encapsulan su propia lógica de validación y autorización. Para crear una clase de solicitud de formulario, puedes usar el comando de Artisan make:request:

php artisan make:request StorePostRequest

La clase de solicitud de formulario generada se ubicará en el directorio app/Http/Requests. Si este directorio no existe, se creará al ejecutar el comando make:request. Cada solicitud de formulario generada por Laravel tiene dos métodos: authorize y rules.

Como podrías haber imaginado, el método authorize es responsable de determinar si el usuario actualmente autenticado puede realizar la acción representada por la solicitud, mientras que el método rules devuelve las reglas de validación que deben aplicarse a los datos de la solicitud:

/**
* Obtener las reglas de validación que se aplican a la solicitud.
*
* @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
*/
public function rules(): array
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}

Nota Puedes indicar el tipo de dependencias que necesitas dentro de la firma del método rules. Se resolverán automáticamente a través del contenedor de servicios de Laravel.

Entonces, ¿cómo se evalúan las reglas de validación? Todo lo que necesitas hacer es hacer una sugerencia de tipo en la solicitud en el método de tu controlador. La solicitud de formulario entrante se valida antes de que se llame al método del controlador, lo que significa que no necesitas llenar tu controlador con ninguna lógica de validación:

/**
* Almacenar una nueva entrada de blog.
*/
public function store(StorePostRequest $request): RedirectResponse
{
// La solicitud entrante es válida...
 
// Obtener los datos de entrada validados...
$validated = $request->validated();
 
// Obtener una parte de los datos de entrada validados...
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
 
// Almacenar la entrada del blog...
 
return redirect('/posts');
}

Si la validación falla, se generará una respuesta de redirección para enviar al usuario de vuelta a su ubicación anterior. Los errores también se almacenarán en la sesión para que estén disponibles para su visualización. Si la solicitud fue una solicitud XHR, se devolverá una respuesta HTTP con un código de estado 422 al usuario, incluyendo una representación JSON de los errores de validación.

Nota ¿Necesitas agregar validación de formularios en tiempo real a tu frontend de Laravel con Inertia? Echa un vistazo a Laravel Precognition.

Realización de validaciones adicionales

A veces necesitas realizar validación adicional después de que se haya completado tu validación inicial. Puedes lograr esto usando el método after de la solicitud de formulario.

El método after debe devolver una matriz de funciones o cierres que se invocarán después de que se complete la validación. Las funciones dadas recibirán una instancia de Illuminate\Validation\Validator, lo que te permite generar mensajes de error adicionales si es necesario:

use Illuminate\Validation\Validator;
 
/**
* Obtener las funciones de llamada de validación "after" para la solicitud.
*/
public function after(): array
{
return [
function (Validator $validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field',
'Something is wrong with this field!'
);
}
}
];
}

Como se mencionó, la matriz devuelta por el método after también puede contener clases invocables. El método __invoke de estas clases recibirá una instancia de Illuminate\Validation\Validator:

use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;
 
/**
* Obtener las funciones de llamada de validación "after" para la solicitud.
*/
public function after(): array
{
return [
new ValidateUserStatus,
new ValidateShippingTime,
function (Validator $validator) {
//
}
];
}

Detener en el primer fallo de validación

Al agregar una propiedad stopOnFirstFailure a tu clase de solicitud, puedes informar al validador que debe dejar de validar todos los atributos una vez que haya ocurrido un solo fallo de validación:

/**
* Indica si el validador debería detenerse en el primer fallo de la regla.
*
* @var bool
*/
protected $stopOnFirstFailure = true;

Personalización de la ubicación de redirección

Como se discutió anteriormente, cuando falla la validación de la solicitud de formulario, se generará automáticamente una respuesta de redirección para enviar al usuario de vuelta a su ubicación anterior. Sin embargo, eres libre de personalizar este comportamiento. Para hacerlo, define una propiedad $redirect en tu solicitud de formulario:

/**
* La URI a la que se debe redirigir a los usuarios si la validación falla.
*
* @var string
*/
protected $redirect = '/dashboard';

O, si deseas redirigir a los usuarios a una ruta con nombre, puedes definir una propiedad $redirectRoute en su lugar:

/**
* La ruta a la que se debe redirigir a los usuarios si la validación falla.
*
* @var string
*/
protected $redirectRoute = 'dashboard';

Autorización de solicitudes de formulario

La clase de solicitud de formulario también contiene un método authorize. Dentro de este método, puedes determinar si el usuario autenticado realmente tiene la autoridad para actualizar un recurso dado. Por ejemplo, puedes determinar si un usuario realmente es el propietario de un comentario de blog que está intentando actualizar. Lo más probable es que interactúes con tus portones (gates) y políticas de autorización dentro de este método:

use App\Models\Comment;
 
/**
* Determinar si el usuario tiene autorización para hacer esta solicitud.
*/
public function authorize(): bool
{
$comment = Comment::find($this->route('comment'));
 
return $comment && $this->user()->can('update', $comment);
}

Dado que todas las solicitudes de formulario extienden la clase base de solicitud de Laravel, podemos usar el método user para acceder al usuario actualmente autenticado. También, ten en cuenta la llamada al método route en el ejemplo anterior. Este método te concede acceso a los parámetros URI definidos en la ruta que se está llamando, como el parámetro {comment} en el ejemplo a continuación:

Route::post('/comment/{comment}');

Por lo tanto, si tu aplicación está aprovechando el enlace de modelos de ruta, tu código puede ser aún más conciso accediendo al modelo resuelto como una propiedad de la solicitud:

return $this->user()->can('update', $this->comment);

Si el método authorize devuelve false, se devolverá automáticamente una respuesta HTTP con un código de estado 403 y no se ejecutará el método de tu controlador.

Si planeas manejar la lógica de autorización para la solicitud en otra parte de tu aplicación, simplemente puedes devolver true desde el método authorize:

/**
* Determinar si el usuario tiene autorización para hacer esta solicitud.
*/
public function authorize(): bool
{
return true;
}

Nota Puedes indicar el tipo de dependencias que necesitas dentro de la firma del método authorize. Se resolverán automáticamente a través del contenedor de servicios de Laravel.

Personalización de los mensajes de error

Puedes personalizar los mensajes de error utilizados por la solicitud de formulario sobrescribiendo el método messages. Este método debe devolver una matriz de pares de atributos/reglas y sus mensajes de error correspondientes:

/**
* Obtener los mensajes de error para las reglas de validación definidas.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}

Personalización de los atributos de validación

Muchos de los mensajes de error de las reglas de validación integradas de Laravel contienen un marcador de posición :attribute. Si deseas que el marcador de posición :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 debe devolver una matriz de pares de atributos/nombres:

/**
* Obtener atributos personalizados para los errores del validador.
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'email' => 'email address',
];
}

Preparación de la entrada para la validación

Si necesitas preparar o sanear algún dato de la solicitud antes de aplicar tus reglas de validación, puedes usar el método prepareForValidation:

use Illuminate\Support\Str;
 
/**
* Preparar los datos para la validación.
*/
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}

Del mismo modo, si necesitas normalizar algún dato de la solicitud después de que se haya completado la validación, puedes usar el método passedValidation:

/**
* Manejar un intento de validación pasado.
*/
protected function passedValidation(): void
{
$this->replace(['name' => 'Taylor']);
}

Creación manual de validadores

Si no deseas usar el método validate en la solicitud, puedes crear manualmente una instancia del validador usando el facade Validator. El método make en el facade genera una nueva instancia de validador:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
 
class PostController extends Controller
{
/**
* Almacenar una nueva entrada de blog.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
 
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator)
->withInput();
}
 
// Obtener la entrada validada...
$validated = $validator->validated();
 
// Obtener una parte de la entrada validada...
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
 
// Almacenar la entrada del blog...
 
return redirect('/posts');
}
}

El primer argumento pasado al método make es los datos bajo validación. El segundo argumento es una matriz de las reglas de validación que deben aplicarse a los datos.

Después de determinar si la validación de la solicitud falló, puedes usar el método withErrors para almacenar los mensajes de error en la sesión. Al usar este método, la variable $errors se compartirá automáticamente con tus vistas después de la redirección, lo que te permitirá mostrarlos fácilmente al usuario. El método withErrors acepta un validador, un MessageBag o un arreglo PHP.

Detener en el primer fallo de validación

El método stopOnFirstFailure informará al validador que debe dejar de validar todos los atributos una vez que haya ocurrido un solo fallo de validación:

if ($validator->stopOnFirstFailure()->fails()) {
// ...
}

Redirección automática

Si deseas crear manualmente una instancia del validador pero aún así aprovechar la redirección automática ofrecida por el método validate de la solicitud HTTP, puedes llamar al método validate en una instancia de validador existente. Si la validación falla, el usuario será redirigido automáticamente o, en el caso de una solicitud XHR, se devolverá una respuesta JSON:

Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();

Puedes usar el método validateWithBag para almacenar los mensajes de error en una bolsa de errores con nombre si la validación falla:

Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validateWithBag('post');

Bolsas de errores con nombre

Si tienes varios formularios en una sola página, es posible que desees nombrar la MessageBag que contiene los errores de validación, lo que te permitirá recuperar los mensajes de error para un formulario específico. Para lograr esto, pasa un nombre como segundo argumento a withErrors:

return redirect('register')->withErrors($validator, 'login');

Luego puedes acceder a la instancia MessageBag con nombre desde la variable $errors:

{{ $errors->login->first('email') }}

Personalización de los mensajes de error

Si es necesario, puedes proporcionar mensajes de error personalizados que una instancia del validador debe usar en lugar de los mensajes de error predeterminados proporcionados por Laravel. Hay varias formas de especificar mensajes personalizados. Primero, puedes pasar los mensajes personalizados como tercer argumento al método Validator::make:

$validator = Validator::make($input, $rules, $messages = [
'required' => 'The :attribute field is required.',
]);

En este ejemplo, el marcador de posición :attribute se reemplazará por el nombre real del campo en validación. También puedes utilizar otros marcadores de posición en los 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',
];

Especificación de un mensaje personalizado para un atributo dado

A veces puedes desear especificar un mensaje de error personalizado solo para un atributo específico. Puedes hacerlo usando la notación "dot". Especifica primero el nombre del atributo, seguido por la regla:

$messages = [
'email.required' => 'We need to know your email address!',
];

Especificación de valores de atributo personalizados

Muchos de los mensajes de error integrados de Laravel incluyen un marcador de posición :attribute que se reemplaza con el nombre del campo o atributo en validación. Para personalizar los valores utilizados para reemplazar estos marcadores de posición para campos específicos, puedes pasar una matriz de atributos personalizados como cuarto argumento al método Validator::make:

$validator = Validator::make($input, $rules, $messages, [
'email' => 'email address',
]);

Realización de validaciones adicionales

A veces necesitas realizar validación adicional después de que se haya completado tu validación inicial. Puedes lograr esto usando el método after del validador. El método after acepta un cierre o una matriz de funciones que se invocarán después de que se complete la validación. Las funciones dadas recibirán una instancia de Illuminate\Validation\Validator, lo que te permitirá generar mensajes de error adicionales si es necesario:

use Illuminate\Support\Facades\Validator;
 
$validator = Validator::make(/* ... */);
 
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field', 'Something is wrong with this field!'
);
}
});
 
if ($validator->fails()) {
// ...
}

Como se señaló, el método after también acepta una matriz de funciones, lo cual es particularmente conveniente si tu lógica de "después de la validación" está encapsulada en clases invocables, que recibirán una instancia de Illuminate\Validation\Validator a través de su método __invoke:

use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
 
$validator->after([
new ValidateUserStatus,
new ValidateShippingTime,
function ($validator) {
// ...
},
]);

Trabajo con entrada validada

Después de validar los datos de la solicitud entrante mediante una solicitud de formulario o una instancia de validador creada manualmente, es posible que desees recuperar los datos de la solicitud entrante que realmente se sometieron a validación. Esto se puede lograr de varias maneras. Primero, puedes llamar al método validated en una solicitud de formulario o instancia de validador. Este método devuelve una matriz de los datos que se validaron:

$validated = $request->validated();
 
$validated = $validator->validated();

Alternativamente, puedes llamar al método safe en una solicitud de formulario o instancia de validador. Este método devuelve una instancia de Illuminate\Support\ValidatedInput. Este objeto expone los métodos only, except, y all para recuperar un subconjunto de los datos validados o la matriz completa de datos validados:

$validated = $request->safe()->only(['name', 'email']);
 
$validated = $request->safe()->except(['name', 'email']);
 
$validated = $request->safe()->all();

Además, la instancia de Illuminate\Support\ValidatedInput se puede recorrer y acceder como si fuera una matriz:

// Los datos validados pueden ser iterados...
foreach ($request->safe() as $key => $value) {
// ...
}
 
// Los datos validados pueden ser accedidos como un array...
$validated = $request->safe();
 
$email = $validated['email'];

Si deseas agregar campos adicionales a los datos validados, puedes llamar al método merge:

$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);

Si deseas recuperar los datos validados como una colección, puedes llamar al método collect:

$collection = $request->safe()->collect();

Trabajo con mensajes de error

Después de llamar al método errors en una instancia de Validator, recibirás una instancia de Illuminate\Support\MessageBag, que tiene una variedad de métodos convenientes para trabajar con mensajes de error. La variable $errors que se pone automáticamente a disposición de todas las vistas también es una instancia de la clase MessageBag.

Recuperación del primer mensaje de error para un campo

Para recuperar el primer mensaje de error para un campo dado, usa el método first:

$errors = $validator->errors();
 
echo $errors->first('email');

Recuperación de todos los mensajes de error para un campo

Si necesitas recuperar una matriz 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 matriz, puedes recuperar todos los mensajes para cada uno de los elementos de la matriz usando el carácter *:

foreach ($errors->get('attachments.*') as $message) {
// ...
}

Recuperación de todos los mensajes de error para todos los campos

Para recuperar una matriz de todos los mensajes para todos los campos, usa el método all:

foreach ($errors->all() as $message) {
// ...
}

Determinación de si existen mensajes para un campo

El método has se puede utilizar para determinar si existen mensajes de error para un campo dado:

if ($errors->has('email')) {
// ...
}

Especificación de mensajes personalizados en archivos de idioma

Las reglas de validación integradas de Laravel tienen un mensaje de error que se encuentra en el archivo lang/en/validation.php de tu aplicación. Si tu aplicación no tiene un directorio lang, puedes indicarle a Laravel que lo cree utilizando el comando de Artisan lang:publish.

Dentro del archivo lang/en/validation.php, encontrarás una entrada de traducción para cada regla de validación. Eres libre de cambiar o modificar estos mensajes según las necesidades de tu aplicación.

Además, puedes copiar este archivo a otro directorio de idiomas para traducir los mensajes al idioma de tu aplicación. Para obtener más información sobre la localización en Laravel, consulta la documentación completa de localización.

Advertencia Por defecto, el esqueleto de la aplicación Laravel no incluye el directorio lang. Si deseas personalizar los archivos de idioma de Laravel, puedes publicarlos mediante el comando Artisan lang:publish.

Mensajes personalizados para atributos específicos

Puedes personalizar los mensajes de error utilizados para combinaciones específicas de atributos y reglas dentro de los archivos de idioma de validación de tu aplicación. Para hacerlo, agrega tus personalizaciones de mensajes al conjunto custom del archivo de idioma lang/xx/validation.php de tu aplicación:

'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],

Especificación de atributos en archivos de idioma

Muchos de los mensajes de error integrados de Laravel incluyen un marcador de posición :attribute que se reemplaza por el nombre del campo o atributo en validación. Si deseas que la porción :attribute de tu mensaje de validación se reemplace con un valor personalizado, puedes especificar el nombre del atributo personalizado en la matriz attributes de tu archivo de idioma lang/xx/validation.php:

'attributes' => [
'email' => 'email address',
],

Advertencia Por defecto, el esqueleto de la aplicación Laravel no incluye el directorio lang. Si deseas personalizar los archivos de idioma de Laravel, puedes publicarlos mediante el comando Artisan lang:publish.

Especificación de valores en archivos de idioma

Algunos de los mensajes de error de reglas de validación integradas de Laravel contienen un marcador de posición :value que se reemplaza con el valor actual del atributo de la solicitud. Sin embargo, ocasionalmente, es posible que necesites que la porción :value de tu mensaje de validación se reemplace con 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:

Validator::make($request->all(), [
'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 más amigable para el usuario en tu archivo de idioma lang/xx/validation.php definiendo una matriz values:

'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],

Advertencia Por defecto, el esqueleto de la aplicación Laravel no incluye el directorio lang. Si deseas personalizar los archivos de idioma de Laravel, puedes publicarlos mediante el comando Artisan lang:publish.

Después de definir este valor, la regla de validación producirá el siguiente mensaje de error:

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 de todas las reglas de validación disponibles y su función:

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" u campos similares.

accepted_if:anotherfield,value,...

El campo bajo validación debe ser \"yes\", \"on\", 1 o true si otro campo bajo validación es igual a un valor especificado. Esto es útil para validar la aceptación de "Términos de servicio" u campos similares.

active_url

El campo bajo validación debe tener un registro A o AAAA válido según la función dns_get_record de PHP. El nombre de host de la URL proporcionada se extrae utilizando la función parse_url de PHP antes de pasarse a dns_get_record.

after:date

El campo bajo validación debe ser un valor posterior a una fecha dada. Las fechas se pasarán a la función strtotime de PHP para convertirlas en una instancia válida de DateTime:

'start_date' => 'required|date|after:tomorrow'

En lugar de pasar una cadena de fecha para que sea evaluada por strtotime, puedes especificar otro campo con el que comparar la fecha:

'finish_date' => 'required|date|after:start_date'

after_or_equal:date

El campo bajo validación debe ser un valor posterior o igual a la fecha dada. Para obtener más información, consulta la regla after.

alpha

El campo bajo validación debe consistir completamente en caracteres alfabéticos Unicode contenidos en \p{L} y \p{M}.

Para restringir esta regla de validación a caracteres en el rango ASCII (a-z y A-Z), puedes proporcionar la opción ascii a la regla de validación:

'username' => 'alpha:ascii',

alpha_dash

El campo bajo validación debe ser completamente caracteres alfanuméricos Unicode contenidos en \p{L}, \p{M}, \p{N}, así como guiones ASCII (-) y guiones bajos ASCII (_).

Para restringir esta regla de validación a caracteres en el rango ASCII (a-z y A-Z), puedes proporcionar la opción ascii a la regla de validación:

'username' => 'alpha_dash:ascii',

alpha_num

El campo bajo validación debe ser completamente caracteres alfanuméricos Unicode contenidos en \p{L}, \p{M}, y \p{N}.

Para restringir esta regla de validación a caracteres en el rango ASCII (a-z y A-Z), puedes proporcionar la opción ascii a la regla de validación:

'username' => 'alpha_num:ascii',

array

El campo bajo validación debe ser un PHP array.

Cuando se proporcionan valores adicionales a la regla array, cada clave en el array de entrada debe estar presente en la lista de valores proporcionados a la regla. En el siguiente ejemplo, la clave admin en el array de entrada no es válida, ya que no está contenida en la lista de valores proporcionados a la regla array:

use Illuminate\Support\Facades\Validator;
 
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
 
Validator::make($input, [
'user' => 'array:name,username',
]);

En general, siempre debes especificar las claves de array que se permiten estar presentes en tu array.

ascii

El campo bajo validación debe consistir completamente en caracteres ASCII de 7 bits.

bail

Deja de ejecutar las reglas de validación para el campo después del primer fallo de validación.

Mientras que la regla bail solo dejará de validar un campo específico cuando encuentre un fallo de validación, el método stopOnFirstFailure informará al validador que debe dejar de validar todos los atributos una vez que ocurra un solo fallo de validación:

if ($validator->stopOnFirstFailure()->fails()) {
// ...
}

before:date

El campo bajo validación debe ser un valor anterior a la fecha dada. Las fechas se pasarán a la función strtotime de PHP para convertirlas en una instancia válida de DateTime. Además, al igual que con la regla after, se puede suministrar el nombre de otro campo bajo validación como el valor de date.

before_or_equal:date

El campo bajo validación debe ser un valor anterior o igual a la fecha dada. Las fechas se pasarán a la función strtotime de PHP para convertirlas en una instancia válida de DateTime. Además, al igual que con la regla after, se puede suministrar el nombre de otro campo bajo validación como el valor de date.

between:min,max

El campo bajo validación debe tener un tamaño entre los valores min y max dados (inclusive). Las cadenas, numéricos, arrays y archivos se evalúan de la misma manera que la regla size.

boolean

El campo bajo validación debe poder convertirse a booleano. Las entradas aceptadas son true, false, 1, 0, "1", y "0".

confirmed

El campo bajo validación debe tener un campo coincidente de {field}_confirmation. Por ejemplo, si el campo bajo validación es password, debe haber presente un campo coincidente password_confirmation en la entrada.

current_password

El campo bajo validación debe coincidir con la contraseña del usuario autenticado. Puedes especificar un guardia de autenticación utilizando el primer parámetro de la regla:

'password' => 'current_password:api'

date

El campo bajo validación debe ser una fecha válida y no relativa según la función strtotime de PHP.

date_equals:date

El campo bajo validación debe ser igual a la fecha dada. Las fechas se pasarán a la función strtotime de PHP para convertirlas en una instancia válida de DateTime.

date_format:format,...

El campo bajo validación debe coincidir con uno de los formatos dados. Debes usar solo date o date_format al validar un campo, no ambos. Esta regla de validación admite todos los formatos admitidos por la clase DateTime de PHP.

decimal:min,max

El campo bajo validación debe ser numérico y debe contener el número especificado de lugares decimales:

// Debe tener exactamente dos decimales (9.99)...
'price' => 'decimal:2'
 
// Debe tener entre 2 y 4 decimales...
'price' => 'decimal:2,4'

declined

El campo bajo validación debe ser "no", "off", 0 o false.

declined_if:anotherfield,value,...

El campo bajo validación debe ser "no", "off", 0 o false si otro campo bajo validación es igual a un valor especificado.

different:field

El campo bajo validación debe tener un valor diferente al de field.

digits:value

El entero bajo validación debe tener una longitud exacta de value.

digits_between:min,max

La validación del entero debe tener una longitud entre los valores min y max dados.

dimensions

El archivo bajo validación debe ser una imagen que cumpla con las restricciones de dimensiones 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 de ratio debe representarse como ancho dividido por alto. Esto se puede especificar ya sea como una fracción como 3/2 o un flotante como 1.5:

'avatar' => 'dimensions:ratio=3/2'

Dado que esta regla requiere varios argumentos, puedes usar el método Rule::dimensions para construir la regla de manera fluida:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
],
]);

distinct

Al validar arrays, el campo bajo validación no debe tener valores duplicados:

'foo.*.id' => 'distinct'

Distinct utiliza comparaciones de variables laxas por defecto. Para usar comparaciones estrictas, puedes agregar el parámetro strict a la definición de la regla de validación:

'foo.*.id' => 'distinct:strict'

Puedes agregar ignore_case a los argumentos de la regla de validación para que la regla ignore las diferencias de mayúsculas y minúsculas:

'foo.*.id' => 'distinct:ignore_case'

doesnt_start_with:foo,bar,...

El campo bajo validación no debe comenzar con ninguno de los valores dados.

doesnt_end_with:foo,bar,...

El campo bajo validación no debe terminar con ninguno de los valores dados.

email

El campo bajo validación debe tener el formato de una dirección de correo electrónico. Esta regla de validación utiliza el paquete egulias/email-validator para validar la dirección de correo electrónico. Por defecto, se aplica el validador RFCValidation, pero también puedes aplicar otros estilos de validación:

'email' => 'email:rfc,dns'

El ejemplo anterior aplicará las validaciones RFCValidation y DNSCheckValidation. Aquí tienes una lista completa de estilos de validación que puedes aplicar:

  • rfc: RFCValidation
  • strict: NoRFCWarningsValidation
  • dns: DNSCheckValidation
  • spoof: SpoofCheckValidation
  • filter: FilterEmailValidation
  • filter_unicode: FilterEmailValidation::unicode()

El validador filter, que utiliza la función filter_var de PHP, se incluye con Laravel y fue el comportamiento de validación de correo electrónico predeterminado de Laravel antes de la versión 5.8.

Advertencia 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.

enum

La regla Enum es una regla basada en clases que valida si el campo bajo validación contiene un valor de enumeración válido. La regla Enum acepta el nombre de la enumeración como su único argumento de constructor:

use App\Enums\ServerStatus;
use Illuminate\Validation\Rule;
 
$request->validate([
'status' => [Rule::enum(ServerStatus::class)],
]);

exclude

El campo bajo validación se excluirá de los datos de solicitud devueltos por los métodos validate y validated.

exclude_if:anotherfield,value

El campo bajo validación se excluirá de los datos de solicitud devueltos por los métodos validate y validated si el campo anotherfield es igual a value.

Si se requiere una lógica de exclusión condicional compleja, puedes utilizar el método Rule::excludeIf. Este método acepta un booleano o un cierre. Cuando se le da un cierre, el cierre debe devolver true o false para indicar si se debe excluir el campo bajo validación:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($request->all(), [
'role_id' => Rule::excludeIf($request->user()->is_admin),
]);
 
Validator::make($request->all(), [
'role_id' => Rule::excludeIf(fn () => $request->user()->is_admin),
]);

exclude_unless:anotherfield,value

El campo bajo validación se excluirá de los datos de solicitud devueltos por los métodos validate y validated a menos que el campo anotherfield sea igual a value. Si value es null (exclude_unless:name,null), el campo bajo validación se excluirá a menos que el campo de comparación sea null o el campo de comparación falte en los datos de la solicitud.

exclude_with:anotherfield

El campo bajo validación se excluirá de los datos de solicitud devueltos por los métodos validate y validated si el campo anotherfield está presente.

exclude_without:anotherfield

El campo bajo validación se excluirá de los datos de solicitud devueltos por los métodos validate y validated si el campo anotherfield no está presente.

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 no se especifica la opción column, se utilizará el nombre del campo. Entonces, en este caso, la regla validará que la tabla de base de datos states contiene un registro con un valor de columna state que coincida con el valor del atributo state de la solicitud.

Especificar un nombre de columna personalizado

Puedes especificar explícitamente el nombre de la columna de la base de datos que se debe usar para la regla de validación al colocarlo después del nombre de la tabla de la base de datos:

'state' => 'exists:states,abbreviation'

Ocasionalmente, es posible que necesites especificar una conexión de base de datos específica que se utilizará para la consulta exists. Puedes lograr esto anteponiendo el nombre de la conexión al nombre de la tabla:

'email' => 'exists:connection.staff,email'

En lugar de especificar directamente el nombre de la tabla, puedes especificar el modelo Eloquent que se utilizará para determinar el nombre de la tabla:

'user_id' => 'exists:App\Models\User,id'

Si deseas personalizar la consulta ejecutada por la regla de validación, puedes usar la clase Rule para definir la regla de manera fluida. En este ejemplo, también especificaremos las reglas de validación como un array en lugar de usar el carácter | para delimitarlas:

use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function (Builder $query) {
return $query->where('account_id', 1);
}),
],
]);

Puedes especificar explícitamente el nombre de la columna de la base de datos que se utilizará para la regla exists generada por el método Rule::exists proporcionando el nombre de la columna como segundo argumento al método exists:

'state' => Rule::exists('states', 'abbreviation'),

file

El campo bajo validación debe ser un archivo cargado con éxito.

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 o el valor dado. Ambos campos deben ser del mismo tipo. Las cadenas, numéricos, arrays y 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 o el valor dado. Ambos campos deben ser del mismo tipo. Las cadenas, numéricos, arrays y archivos se evalúan utilizando las mismas convenciones que la regla size.

image

El archivo bajo validación debe ser una imagen (jpg, jpeg, png, bmp, gif, svg o webp).

in:foo,bar,...

El campo bajo validación debe estar incluido en la lista dada de valores. Dado que esta regla a menudo requiere que hagas implode de un array, puedes usar el método Rule::in para construir la regla de manera fluida:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);

Cuando la regla in se combina con la regla array, cada valor en el array de entrada debe estar presente dentro de la lista de valores proporcionada a la regla in. En el siguiente ejemplo, el código de aeropuerto LAS en el array de entrada no es válido ya que no está contenido en la lista de aeropuertos proporcionada a la regla in:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
$input = [
'airports' => ['NYC', 'LAS'],
];
 
Validator::make($input, [
'airports' => [
'required',
'array',
],
'airports.*' => Rule::in(['NYC', 'LIT']),
]);

in_array:anotherfield.*

El campo bajo validación debe existir en los valores de anotherfield.

integer

El campo bajo validación debe ser un entero.

Advertencia Esta regla de validación no verifica que la entrada sea del tipo de variable "integer", solo que la entrada sea de un tipo aceptado por la regla FILTER_VALIDATE_INT de PHP. Si necesitas validar la entrada como un número, utiliza esta regla en combinación con la regla de validación numeric.

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 campo o el valor dado. Ambos campos deben ser del mismo tipo. Las cadenas, numéricos, arrays y 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 campo o el valor dado. Ambos campos deben ser del mismo tipo. Las cadenas, numéricos, arrays y archivos se evalúan utilizando las mismas convenciones que la regla size.

lowercase

El campo bajo validación debe estar en minúsculas.

mac_address

El campo bajo validación debe ser una dirección MAC.

max:value

El campo bajo validación debe ser menor o igual a un máximo value. Las cadenas, numéricos, arrays y archivos se evalúan de la misma manera que la regla size.

max_digits:value

El entero bajo validación debe tener una longitud máxima de value.

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, se leerán los contenidos del archivo y el framework intentará adivinar el tipo MIME, que puede ser diferente del tipo MIME proporcionado por el cliente.

mimes:foo,bar,...

El archivo bajo validación debe tener un tipo MIME correspondiente a una de las extensiones enumeradas.

Basic Usage Of MIME Rule

'photo' => 'mimes:jpg,bmp,png'

Aunque solo necesitas especificar las extensiones, esta regla realmente valida el tipo MIME del archivo leyendo los contenidos del archivo y adivinando su tipo MIME. Puedes encontrar una lista completa de tipos MIME y sus extensiones correspondientes 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 debe tener un valor mínimo value. Las cadenas, numéricos, arrays y archivos se evalúan de la misma manera que la regla size.

min_digits:value

El entero bajo validación debe tener una longitud mínima de value.

multiple_of:value

El campo bajo validación debe ser un múltiplo de value.

missing

El campo bajo validación no debe estar presente en los datos de entrada.

missing_if:anotherfield,value,...

El campo bajo validación no debe estar presente si el campo anotherfield es igual a alguno de los value.

missing_unless:anotherfield,value

El campo bajo validación no debe estar presente a menos que el campo anotherfield sea igual a alguno de los value.

missing_with:foo,bar,...

El campo bajo validación no debe estar presente solo si alguno de los otros campos especificados está presente.

missing_with_all:foo,bar,...

El campo bajo validación no debe estar presente solo si todos los otros campos especificados están presentes.

not_in:foo,bar,...

El campo bajo validación no debe estar incluido en la lista dada de valores. El método Rule::notIn se puede utilizar para construir la regla de manera fluida:

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 utiliza la función preg_match de PHP. El patrón especificado debe cumplir con el mismo formato requerido por preg_match y, por lo tanto, también debe incluir delimitadores válidos. Por ejemplo: 'email' => 'not_regex:/^.+$/i'.

Advertencia Cuando se utilizan patrones regex / not_regex, puede ser necesario especificar tus reglas de validación utilizando una matriz en lugar de usar delimitadores |, especialmente si la expresión regular contiene el carácter |.

nullable

El campo bajo validación puede ser null.

numeric

El campo bajo validación debe ser numérico.

password

El campo bajo validación debe coincidir con la contraseña del usuario autenticado.

Advertencia Esta regla fue renombrada a current_password con la intención de eliminarla en Laravel 9. Utiliza la regla Current Password en su lugar.

present

El campo bajo validación debe existir en los datos de entrada.

prohibited

El campo bajo validación debe estar ausente o vacío. Un campo está "vacío" si cumple con uno de los siguientes criterios:

  • El valor es null.
  • El valor es una cadena vacía.
  • El valor es un array vacío u objeto Countable vacío.
  • El valor es un archivo cargado con una ruta vacía.

prohibited_if:anotherfield,value,...

El campo bajo validación debe estar ausente o vacío si el campo anotherfield es igual a alguno de los value. Un campo está "vacío" si cumple con uno de los siguientes criterios:

  • El valor es null.
  • El valor es una cadena vacía.
  • El valor es un array vacío u objeto Countable vacío.
  • El valor es un archivo cargado con una ruta vacía.

Si se requiere una lógica de prohibición condicional compleja, puedes utilizar el método Rule::prohibitedIf. Este método acepta un booleano o un cierre. Cuando se le da un cierre, el cierre debe devolver true o false para indicar si se debe prohibir el campo bajo validación:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($request->all(), [
'role_id' => Rule::prohibitedIf($request->user()->is_admin),
]);
 
Validator::make($request->all(), [
'role_id' => Rule::prohibitedIf(fn () => $request->user()->is_admin),
]);

prohibited_unless:anotherfield,value,...

El campo bajo validación debe estar ausente o vacío a menos que el campo anotherfield sea igual a alguno de los value. Un campo está "vacío" si cumple con uno de los siguientes criterios:

  • El valor es null.
  • El valor es una cadena vacía.
  • El valor es un array vacío u objeto Countable vacío.
  • El valor es un archivo cargado con una ruta vacía.

prohibits:anotherfield,...

Si el campo bajo validación no está ausente o vacío, todos los campos en anotherfield deben estar ausentes o vacíos. Un campo está "vacío" si cumple con uno de los siguientes criterios:

  • El valor es null.
  • El valor es una cadena vacía.
  • El valor es un array vacío u objeto Countable vacío.
  • El valor es un archivo cargado con una ruta vacía.

regex:pattern

El campo bajo validación debe coincidir con la expresión regular dada.

Internamente, esta regla utiliza la función preg_match de PHP. El patrón especificado debe obedecer el mismo formato requerido por preg_match y, por lo tanto, también debe incluir delimitadores válidos. Por ejemplo: 'email' => 'regex:/^.+@.+$/i'.

Advertencia Cuando se utilizan patrones regex / not_regex, puede ser necesario especificar reglas en una matriz en lugar de usar delimitadores |, especialmente si la expresión regular contiene el carácter |.

required

El campo bajo validación debe estar presente en los datos de entrada y no debe estar vacío. Un campo está "vacío" si cumple con uno de los siguientes criterios:

  • El valor es null.
  • El valor es una cadena vacía.
  • El valor es un array vacío u 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 alguno de los 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 booleano o un cierre. Cuando se pasa un cierre, el cierre debe devolver true o false para indicar si se requiere el campo bajo validación:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($request->all(), [
'role_id' => Rule::requiredIf($request->user()->is_admin),
]);
 
Validator::make($request->all(), [
'role_id' => Rule::requiredIf(fn () => $request->user()->is_admin),
]);

required_if_accepted:_anotherfield,...

El campo bajo validación debe estar presente y no vacío si el campo anotherfield es igual a yes, on, 1, \"1\", true o \"true\".

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 alguno de los value. Esto también significa que anotherfield debe estar presente en los datos de la solicitud a menos que value sea null. Si value es null (required_unless:name,null), el campo bajo validación será requerido a menos que el campo de comparación sea null o falte en los datos de la solicitud.

required_with:foo,bar,...

El campo bajo validación debe estar presente y no vacío solo si alguno de los otros campos especificados está presente y no vacío.

required_with_all:foo,bar,...

El campo bajo validación debe estar presente y no vacío solo si todos los otros campos especificados están presentes y no vacíos.

required_without:foo,bar,...

El campo bajo validación debe estar presente y no vacío solo cuando alguno de los otros campos especificados está vacío o no está presente.

required_without_all:foo,bar,...

El campo bajo validación debe estar presente y no vacío solo cuando todos los otros campos especificados están vacíos o no están presentes.

required_array_keys:foo,bar,...

El campo bajo validación debe ser un array y debe contener al menos las claves especificadas.

same:field

El field dado debe coincidir con el campo bajo validación.

size:value

El campo bajo validación debe tener un tamaño que coincida con el value dado. Para datos de cadena, value corresponde al número de caracteres. Para datos numéricos, value corresponde a un valor entero dado (el atributo también debe tener la regla numeric o integer). Para un array, size corresponde al count del array. Para archivos, size corresponde al tamaño del archivo en kilobytes. Veamos algunos ejemplos:

// Validar que una cadena tenga exactamente 12 caracteres...
'title' => 'size:12';
 
// Validar que un entero proporcionado sea igual a 10...
'seats' => 'integer|size:10';
 
// Validar que un array tenga exactamente 5 elementos...
'tags' => 'array|size:5';
 
// Validar que un archivo cargado sea exactamente de 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 deseas permitir que el campo también sea null, debes asignar la regla nullable al campo.

timezone

El campo bajo validación debe ser un identificador de zona horaria válido según el método DateTimeZone::listIdentifiers.

Los argumentos aceptados por el método DateTimeZone::listIdentifiers también se pueden proporcionar a esta regla de validación:

'timezone' => 'required|timezone:all';
 
'timezone' => 'required|timezone:Africa';
 
'timezone' => 'required|timezone:per_country,US';

unique:table,column

El campo bajo validación no debe existir dentro de la tabla de base de datos dada.

Especificar un Nombre de Tabla / Columna Personalizado:

En lugar de especificar directamente el nombre de la tabla, puedes especificar el modelo Eloquent que se debe usar para determinar el nombre de la tabla:

'email' => 'unique:App\Models\User,email_address'

La opción column se puede usar para especificar la columna de la base de datos correspondiente al campo. Si no se especifica la opción column, se usará el nombre del campo bajo validación.

'email' => 'unique:users,email_address'

Especificar una Conexión de Base de Datos Personalizada

Ocasionalmente, es posible que necesites establecer una conexión personalizada para las consultas de base de datos realizadas por el Validador. Para lograr esto, puedes anteponer el nombre de la conexión al nombre de la tabla:

'email' => 'unique:connection.users,email_address'

Forzar una Regla Única a Ignorar un ID Específico:

A veces, es posible que desees ignorar un ID específico durante la validación única. Por ejemplo, considera una pantalla de "actualizar perfil" que incluye el nombre, la dirección de correo electrónico y la ubicación del usuario. Probablemente desearás verificar que la dirección de correo electrónico sea única. Sin embargo, si el usuario solo cambia el campo de nombre y no el campo de correo electrónico, no querrás que se genere un error de validación porque el usuario ya es el propietario de la dirección de correo electrónico en cuestión.

Para indicar al validador que ignore el ID del usuario, usaremos la clase Rule para definir la regla de manera fluida. En este ejemplo, también especificaremos las reglas de validación como un array en lugar de usar el carácter | para delimitar las reglas:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);

Advertencia Nunca debes pasar ninguna entrada de solicitud controlada por el usuario al método ignore. En su lugar, solo debes pasar un ID único generado por el sistema, como un ID de incremento automático o UUID de una instancia del 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, también puedes pasar la instancia completa del modelo. Laravel extraerá automáticamente la clave del modelo:

Rule::unique('users')->ignore($user)

Si tu tabla usa un nombre de columna de clave primaria que no sea id, puedes especificar el nombre de la columna al llamar al método ignore:

Rule::unique('users')->ignore($user->id, 'user_id')

De forma predeterminada, la regla unique verificará la unicidad de la columna que coincide con el nombre del atributo que se está validando. Sin embargo, puedes pasar un nombre de columna diferente como segundo argumento al método unique:

Rule::unique('users', 'email_address')->ignore($user->id)

Agregar Cláusulas Where Adicionales:

Puedes especificar condiciones de consulta adicionales personalizando la consulta con el método where. Por ejemplo, agreguemos una condición de consulta que limite la búsqueda solo a registros que tengan un valor de columna account_id de 1:

'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))

uppercase

El campo bajo validación debe estar en mayúsculas.

url

El campo bajo validación debe ser una URL válida.

Si deseas especificar los protocolos de URL que deben considerarse válidos, puedes pasar los protocolos como parámetros de reglas de validación:

'url' => 'url:http,https',
 
'game' => 'url:minecraft,steam',

ulid

El campo bajo validación debe ser un Identificador Ordenable Lexicográficamente Único Universal (ULID) válido.

uuid

El campo bajo validación debe ser un identificador único universal (UUID) válido de RFC 4122 (versión 1, 3, 4 o 5).

Adición condicional de reglas

Omitir validación cuando los campos tienen ciertos valores

Ocasionalmente, es posible que no desees validar un campo dado si otro campo tiene un valor específico. Puedes lograr esto usando la regla de validación exclude_if. En este ejemplo, los campos appointment_date y doctor_name no se validarán si el campo has_appointment tiene un valor de false:

use Illuminate\Support\Facades\Validator;
 
$validator = Validator::make($data, [
'has_appointment' => 'required|boolean',
'appointment_date' => 'exclude_if:has_appointment,false|required|date',
'doctor_name' => 'exclude_if:has_appointment,false|required|string',
]);

Alternativamente, puedes usar la regla exclude_unless para no validar un campo dado a menos que otro campo tenga un valor específico:

$validator = Validator::make($data, [
'has_appointment' => 'required|boolean',
'appointment_date' => 'exclude_unless:has_appointment,true|required|date',
'doctor_name' => 'exclude_unless:has_appointment,true|required|string',
]);

Validar cuando está presente

En algunas situaciones, es posible que desees ejecutar controles de validación contra un campo solo si ese campo está presente en los datos que se están validando. Para lograr esto rápidamente, agrega la regla sometimes a tu lista de reglas:

$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);

En el ejemplo anterior, el campo email solo se validará si está presente en el array $data.

Nota Si intentas validar un campo que siempre debe estar presente pero puede estar vacío, consulta esta nota sobre campos opcionales.

Validación condicional compleja

A veces, es posible que desees agregar reglas de validación basadas en lógica condicional más compleja. Por ejemplo, es posible que desees requerir un campo dado solo si otro campo tiene un valor mayor que 100. O tal vez necesitas que dos campos tengan un valor específico solo cuando otro campo está presente. Agregar estas reglas de validación no tiene por qué ser complicado. Primero, crea una instancia de Validator con tus reglas estáticas que nunca cambian:

use Illuminate\Support\Facades\Validator;
 
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'games' => 'required|numeric',
]);

Supongamos que nuestra aplicación web es para coleccionistas de juegos. Si un coleccionista de juegos se registra en nuestra aplicación y posee más de 100 juegos, queremos que expliquen por qué tienen tantos juegos. Por ejemplo, tal vez tienen una tienda de reventa de juegos, o tal vez simplemente disfrutan coleccionando juegos. Para agregar condicionalmente este requisito, podemos usar el método sometimes en la instancia de Validator.

use Illuminate\Support\Fluent;
 
$validator->sometimes('reason', 'required|max:500', function (Fluent $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 es una lista de las reglas que queremos agregar. Si el cierre pasado como tercer argumento devuelve true, se agregarán las reglas. Este método facilita la construcción de validaciones condicionales complejas. Incluso puedes agregar validaciones condicionales para varios campos a la vez:

$validator->sometimes(['reason', 'cost'], 'required', function (Fluent $input) {
return $input->games >= 100;
});

Nota El parámetro $input pasado a tu cierre será una instancia de Illuminate\Support\Fluent y se puede utilizar para acceder a tu entrada y archivos bajo validación.

Validación condicional de matriz compleja

A veces, es posible que desees validar un campo en función de otro campo en el mismo array anidado cuyo índice no conoces. En estas situaciones, puedes permitir que tu cierre reciba un segundo argumento que será el elemento individual actual en el array que se está validando:

$input = [
'channels' => [
[
'type' => 'email',
'address' => '[email protected]',
],
[
'type' => 'url',
'address' => 'https://example.com',
],
],
];
 
$validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
return $item->type === 'email';
});
 
$validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
return $item->type !== 'email';
});

Al igual que el parámetro $input pasado al cierre, el parámetro $item es una instancia de Illuminate\Support\Fluent cuando los datos del atributo son un array; de lo contrario, es una cadena.

Validación de matrices

Como se discutió en la documentación de la regla de validación array, la regla array acepta una lista de claves de array permitidas. Si hay claves adicionales presentes dentro del array, la validación fallará:

use Illuminate\Support\Facades\Validator;
 
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
 
Validator::make($input, [
'user' => 'array:name,username',
]);

En general, siempre debes especificar las claves de array que se permiten estar presentes en tu array. De lo contrario, los métodos validate y validated del validador devolverán todos los datos validados, incluido el array y todas sus claves, incluso si esas claves no fueron validadas por otras reglas de validación de array anidado.

Validación de entrada de matriz anidada

Validar campos de entrada de formularios basados en arrays anidados no tiene por qué ser complicado. Puedes usar la "notación de puntos" para validar atributos dentro de un array. Por ejemplo, si la solicitud HTTP entrante contiene un campo photos[profile], puedes validarlo de la siguiente manera:

use Illuminate\Support\Facades\Validator;
 
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);

También puedes validar cada elemento de un array. Por ejemplo, para validar que cada correo electrónico en un campo de entrada de array dado sea único, puedes hacer lo siguiente:

$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);

Asimismo, puedes usar el carácter * al especificar mensajes de validación personalizados en tus archivos de idioma, facilitando el uso de un solo mensaje de validación para campos basados en arrays:

'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique email address',
]
],

Acceso a datos de matriz anidada

A veces, es posible que necesites acceder al valor de un elemento de array anidado dado al asignar reglas de validación al atributo. Puedes lograr esto usando el método Rule::forEach. El método forEach acepta un cierre que se invocará para cada iteración del atributo de array bajo validación y recibirá el valor del atributo y el nombre del atributo explícito y completamente expandido. El cierre debe devolver un array de reglas para asignar al elemento de array:

use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
$validator = Validator::make($request->all(), [
'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
return [
Rule::exists(Company::class, 'id'),
new HasPermission('manage-company', $value),
];
}),
]);

Índices y posiciones de mensajes de error

Al validar arrays, es posible que desees hacer referencia al índice o posición de un elemento particular que falló en la validación dentro del mensaje de error mostrado por tu aplicación. Para lograr esto, puedes incluir los marcadores :index (comienza desde 0) y :position (comienza desde 1) dentro de tu mensaje de validación personalizado:

use Illuminate\Support\Facades\Validator;
 
$input = [
'photos' => [
[
'name' => 'BeachVacation.jpg',
'description' => 'A photo of my beach vacation!',
],
[
'name' => 'GrandCanyon.jpg',
'description' => '',
],
],
];
 
Validator::validate($input, [
'photos.*.description' => 'required',
], [
'photos.*.description.required' => 'Please describe photo #:position.',
]);

Dado el ejemplo anterior, la validación fallará y el usuario verá el siguiente error: "Por favor, describe la foto #2."

Si es necesario, puedes hacer referencia a índices y posiciones más profundamente anidadas a través de second-index, second-position, third-index, third-position, etc.

'photos.*.attributes.*.string' => 'Invalid attribute for photo #:second-position.',

Validación de archivos

Laravel proporciona una variedad de reglas de validación que se pueden usar para validar archivos cargados, como mimes, image, min y max. Aunque eres libre de especificar estas reglas individualmente al validar archivos, Laravel también ofrece un constructor de reglas de validación de archivos fluido que puede resultar conveniente:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
 
Validator::validate($input, [
'attachment' => [
'required',
File::types(['mp3', 'wav'])
->min(1024)
->max(12 * 1024),
],
]);

Si tu aplicación acepta imágenes cargadas por tus usuarios, puedes usar el método constructor image de la regla File para indicar que el archivo cargado debe ser una imagen. Además, la regla dimensions se puede usar para limitar las dimensiones de la imagen:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
 
Validator::validate($input, [
'photo' => [
'required',
File::image()
->min(1024)
->max(12 * 1024)
->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
],
]);

Nota Puedes encontrar más información sobre la validación de dimensiones de imágenes en la documentación de la regla de dimensiones.

Tamaños de archivos

Por comodidad, los tamaños mínimos y máximos de archivos se pueden especificar como una cadena con un sufijo que indica las unidades de tamaño del archivo. Se admiten los sufijos kb, mb, gb y tb:

File::image()
->min('1kb')
->max('10mb')

Tipos de archivos

Aunque solo necesitas especificar las extensiones al invocar el método types, este método en realidad valida el tipo MIME del archivo leyendo el contenido del archivo y adivinando su tipo MIME. Puedes encontrar una lista completa de tipos MIME y sus extensiones correspondientes en la siguiente ubicación:

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

Validación de contraseñas

Para asegurarte de que las contraseñas tengan un nivel adecuado de complejidad, puedes usar el objeto de regla Password de Laravel:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
 
$validator = Validator::make($request->all(), [
'password' => ['required', 'confirmed', Password::min(8)],
]);

El objeto de regla Password te permite personalizar fácilmente los requisitos de complejidad de las contraseñas para tu aplicación, como especificar que las contraseñas requieren al menos una letra, número, símbolo o caracteres con mayúsculas y minúsculas combinadas:

// Requerir al menos 8 caracteres...
Password::min(8)
 
// Requerir al menos una letra...
Password::min(8)->letters()
 
// Requerir al menos una letra mayúscula y una minúscula...
Password::min(8)->mixedCase()
 
// Requerir al menos un número...
Password::min(8)->numbers()
 
// Requerir al menos un símbolo...
Password::min(8)->symbols()

Además, puedes asegurarte de que una contraseña no se haya comprometido en una filtración de datos de contraseñas pública utilizando el método uncompromised:

Password::min(8)->uncompromised()

Internamente, el objeto de regla Password utiliza el modelo k-Anonymity para determinar si una contraseña se ha filtrado a través del servicio haveibeenpwned.com sin sacrificar la privacidad o seguridad del usuario.

De forma predeterminada, si una contraseña aparece al menos una vez en una filtración de datos, se considerará comprometida. Puedes personalizar este umbral usando el primer argumento del método uncompromised:

// Asegurarse de que la contraseña aparezca menos de 3 veces en la misma filtración de datos...
Password::min(8)->uncompromised(3);

Por supuesto, puedes encadenar todos los métodos en los ejemplos anteriores:

Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised()

Definición de reglas de contraseña predeterminadas

Puede resultarte conveniente especificar las reglas de validación predeterminadas para las contraseñas en un solo lugar de tu aplicación. Puedes hacer esto fácilmente usando el método Password::defaults, que acepta un cierre. El cierre proporcionado al método defaults debe devolver la configuración predeterminada de la regla de contraseña. Por lo general, la regla defaults debe llamarse dentro del método boot de uno de los proveedores de servicios de tu aplicación:

use Illuminate\Validation\Rules\Password;
 
/**
* Inicializar cualquier servicio de la aplicación.
*/
public function boot(): void
{
Password::defaults(function () {
$rule = Password::min(8);
 
return $this->app->isProduction()
? $rule->mixedCase()->uncompromised()
: $rule;
});
}

Luego, cuando desees aplicar las reglas predeterminadas a una contraseña específica que está siendo validada, puedes invocar el método defaults sin argumentos:

'password' => ['required', Password::defaults()],

Ocasionalmente, es posible que desees adjuntar reglas de validación adicionales a tus reglas de validación de contraseña predeterminadas. Puedes usar el método rules para lograr esto:

use App\Rules\ZxcvbnRule;
 
Password::defaults(function () {
$rule = Password::min(8)->rules([new ZxcvbnRule]);
 
// ...
});

Reglas de validación personalizadas

Uso de objetos de regla

Laravel proporciona una variedad de útiles reglas de validación; sin embargo, es posible que desees especificar algunas propias. Un método para registrar reglas de validación personalizadas es mediante el uso de 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úsculas. Laravel colocará la nueva regla en el directorio app/Rules. Si este directorio no existe, Laravel lo creará cuando ejecutes el comando Artisan para crear tu regla:

php artisan make:rule Uppercase

Una vez creada la regla, estamos listos para definir su comportamiento. Un objeto de regla contiene un solo método: validate. Este método recibe el nombre del atributo, su valor y un callback que se debe invocar en caso de error con el mensaje de error de validación:

<?php
 
namespace App\Rules;
 
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
 
class Uppercase implements ValidationRule
{
/**
* Ejecutar la regla de validación.
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (strtoupper($value) !== $value) {
$fail('The :attribute must be uppercase.');
}
}
}

Una vez que se ha definido la regla, puedes adjuntarla a un validador pasando una instancia del objeto de regla con tus otras reglas de validación:

use App\Rules\Uppercase;
 
$request->validate([
'name' => ['required', 'string', new Uppercase],
]);

Traducción de mensajes de validación

En lugar de proporcionar un mensaje de error literal al cierre $fail, también puedes proporcionar una clave de cadena de traducción e indicar a Laravel que traduzca el mensaje de error:

if (strtoupper($value) !== $value) {
$fail('validation.uppercase')->translate();
}

Si es necesario, puedes proporcionar reemplazos de marcadores de posición y el idioma preferido como primer y segundo argumento al método translate:

$fail('validation.location')->translate([
'value' => $this->value,
], 'fr')

Acceso a datos adicionales

Si la clase de regla de validación personalizada necesita acceder a todos los demás datos que se están validando, tu clase de regla puede implementar la interfaz Illuminate\Contracts\Validation\DataAwareRule. Esta interfaz requiere que tu clase defina un método setData. Este método se invocará automáticamente por Laravel (antes de que continúe la validación) con todos los datos que se están validando:

<?php
 
namespace App\Rules;
 
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
 
class Uppercase implements DataAwareRule, ValidationRule
{
/**
* Todos los datos bajo validación.
*
* @var array<string, mixed>
*/
protected $data = [];
 
// ...
 
/**
* Establecer los datos bajo validación.
*
* @param array<string, mixed> $data
*/
public function setData(array $data): static
{
$this->data = $data;
 
return $this;
}
}

O, si tu regla de validación requiere acceso a la instancia del validador que realiza la validación, puedes implementar la interfaz ValidatorAwareRule:

<?php
 
namespace App\Rules;
 
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Validation\Validator;
 
class Uppercase implements ValidationRule, ValidatorAwareRule
{
/**
* La instancia del validador.
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
 
// ...
 
/**
* Establecer el validador actual.
*/
public function setValidator(Validator $validator): static
{
$this->validator = $validator;
 
return $this;
}
}

Uso de cierres

Si solo necesitas la funcionalidad de una regla personalizada una vez en toda tu aplicación, puedes usar un cierre en lugar de un objeto de regla. El cierre recibe el nombre del atributo, el valor del atributo y un callback $fail que se debe llamar si la validación falla:

use Illuminate\Support\Facades\Validator;
use Closure;
 
$validator = Validator::make($request->all(), [
'title' => [
'required',
'max:255',
function (string $attribute, mixed $value, Closure $fail) {
if ($value === 'foo') {
$fail("The {$attribute} is invalid.");
}
},
],
]);

Reglas implícitas

De forma predeterminada, cuando el atributo que se está validando no está presente o contiene una cadena vacía, las reglas de validación normales, incluidas las reglas personalizadas, no se ejecutan. Por ejemplo, la regla unique no se ejecutará contra una cadena vacía:

use Illuminate\Support\Facades\Validator;
 
$rules = ['name' => 'unique:users,name'];
 
$input = ['name' => ''];
 
Validator::make($input, $rules)->passes(); // true

Para que una regla personalizada se ejecute incluso cuando un atributo está vacío, la regla debe implicar que el atributo es obligatorio. Para generar rápidamente un nuevo objeto de regla implícita, puedes usar el comando Artisan make:rule con la opción --implicit:

php artisan make:rule Uppercase --implicit

Advertencia Una regla "implícita" solo implica que el atributo es requerido. Si realmente invalida un atributo que falta o está vacío depende de ti.