Validation

# Introducción

Laravel incluye varias propuestas para validar la entrada de datos de su aplicación. Por defecto, la clase base del controlador de Laravel utiliza el contrato (trait) ValidatesRequests el cuál provee un método para validar la petición HTTP entrante con una gran variedad de reglas de validación muy potentes.

# Comienzo rápido con la validación

Para saber más sobre las características de las potentes reglas de validación, puede echar un vistazo a un ejemplo completo para validar un formulario y mostrar los mensajes de error al usuario.

Definir las rutas

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

use App\Http\Controllers\PostController;

Route::get('post/create', [PostController::class, 'create']);

Route::post('post', [PostController::class, 'store']);

Por supuesto, la ruta GET mostrará un formulario al usuario para crear un nuevo post en un blog, mientas que la ruta POST almacenará ese artículo en la base de datos.

Crear el controlador

A continuación, veamos un controlador simple que gestione estas rutas. Dejaremos el método store vacío por el momento:

<?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

Ya estamos listos para incluir la lógica para validar el nuevo artículo en el método store. Para hacer esto, usaremos el método validate proporcionado por el objeto Illuminate\Http\Request. Si se pasa la regla de validación, el código continuará ejecutándose normalmente; sin embargo, si la regla falla, se lanzará una excepción y la respuesta apropiada será enviada, automáticamente, de vuelta al usuario. En el caso de una petición HTTP tradicional, se generará una respuesta de redirección, mientras que para peticiones AJAX se enviará una respuesta en formato JSON.

Para entender mejor el método validate, veamos el interior del 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 se puede observar, simplemente se pasamos las reglas de validación deseadas al método validate. De nuevo, si la validación falla, será generada una apropiada respuesta de forma automática. Si la validación pasa, el controlador continuará ejecutándose con normalidad.

Alternativamente, las reglas de validación pueden especificarse como matrices de reglas en lugar de una única cadena delimitada:

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

Puedes utilizar el método validateWithBag ara validar una solicitud y almacenar cualquier mensaje de error dentro de una Bolsa de error con nombre:

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

Detener la validación en el primer fallo

A veces puede que quiera deterner la validación en curso en un atributo después del primer error de validación. Para ello, asigne 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 de validación max no es comprobada. Las reglas son validadas en el orden que son asignadas.

Consideraciones sobre los atributos anidados

Si su petición HTTP contiene parámetros "anidados", puede especificarlos en las reglas de validación utilizando la notación de "puntos":

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

Por otra parte, si su nombre de campo contiene un período literal, puede evitar explícitamente que esto se interprete como una sintaxis de "punto" escapando del período con una barra invertida:

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

Mostrar los errores de validación

Ahora, ¿qué sucede si los parámetros de validación entrantes no pasan las reglas de validación? Como se mencionó anteriormente, Laravel redireccionará automáticamente al usuario a su ubicación anterior. Además, todos los errores de validación serán flashed automáticamente a la session.

De nuevo, noten que no tuvimos que vincular explícitamente los mensajes de error a la vista en nuestra ruta GET. Esto se debe a que Laravel comprobará si hay errores en los datos de la sesión, y los vinculará automáticamente a la vista si están disponibles. La variable $errors será una instancia de Illuminate\Support\MessageBag. Para más información sobre el trabajo con este objeto,  compruebe su documentación.

La variable $errors está vinculada a la vista por el middleware Illuminate\View\Middleware\ShareErrorsFromSession, que es proporcionado por el grupo del middleware web. Cuando este middleware se aplica una variable $errors iempre estará disponible en sus vistas, permitiéndole asumir convenientemente que la variable $errors vestá siempre definida 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 -->

La directiva @error

También puede utilizar la directiva Blade @error para comprobar rápidamente si existen mensajes de error de validación para un atributo determinado. Dentro de una directiva @error,puedes hacer echo de 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

Nota sobre los campos opcionales

Por defecto, Laravel incluye el middleware TrimStringsConvertEmptyStringsToNull en la pila global de middleware de su aplicación. Estos middleware están listados en la pila por la clase App\Http\Kernel. Debido a esto, a menudo tendrás que marcar tus campos de solicitud "opcionales" como nullable si no quieres que el validador considere los valores null como invá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 la representación de una fecha válida. Si el modificador nullable no es añadido a la definición de la regla, el validador se consideraría null como una fecha invalida.

Peticiones Ajax y Validación

En este ejemplo, utilizamos un formulario tradicional para enviar datos a la aplicación. Sin embargo, muchas aplicaciones utilizan peticiones AJAX. Cuando usamos el método validate durante una petición AJAX, Laravel no generará automáticamente una respuesta de redirección. En su lugar, genera una respuesta JSON conteniendo todos los errores de validación. Esta respuesta JSON se enviará con un código de estado HTTP 422.

# Form Request Validation

Crear Form Requests

Para escenarios de validación más complejos, tal vez desee crear una "solicitud de formulario". Las solicitudes de formularios son clases de solicitud personalizadas que contienen una lógica de validación. Para crear una clase de solicitud de formulario, utilice el comando de la Artisan CLI make:request:

php artisan make:request StoreBlogPost

La clase generada será guardadad en el directorio app/Http/Requests. Si el directorio no existe, será creado automáticamente cuando ejecute el comando make:request. Agretemos unas pocas 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 escribir a máquina cualquier dependencia que necesites dentro de la firma del método  rules. Se resolverán automáticamente a través del service container de Laravel.

Entonces, ¿cómo se evalúan las reglas de validación? Todo lo que necesitas hacer es teclear la petición en tu método de control. La solicitud de formulario entrante se valida antes de que se llame al método controlador, lo que significa que no es necesario sobrecargar el 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, se generará una respuesta de redireccionamiento para enviar al usuario de vuelta a su ubicación anterior. Los errores también se mostrarán en la sesión para que estén disponibles para su visualización. Si la solicitud era 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.

Agregar Hooks a los Form Requests

Si se desea agregar un hook "posterior" a una petición de formulario (form request), puede usar el método withValidator. Este método recibe el validador totalmente construido, permitiéndole llamar a cualquiera de sus métodos antes que las reglas de validación sean realmente evaluadas:

/**
 * 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!');
        }
    });
}

Autorización de los Form Requests

Las clases form request tambien contienen un metodo authorize. Dentro de este método, usted puede comprobar si el usuario autenticado tiene realmente el permiso para actualizar un recurso determinado. Por ejemplo, usted puede determinar si un usuario es, realmente, dueño de un comentario de un blog que esta 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 todos los Form Requests extienden de la clase base Request de Laravel, se puede utilizar el método user para acceder al usuario autenticado. También observe la llamada al método route en el ejemplo anterior. Este método le garantiza el acceso a los parámetros de la URI definidos en la ruta que se está siendo llamada, como el parámetro {comment} en el siguiente ejemplo:

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

Si el método authorize retorna false, es devuelta automáticamente una respuesta HTTP con un estado 403 y el método de su controlador no es ejecutado.

Si su plan es tener una lógica de autorización en otra parte de la aplicación, simplemente retorne true en el método authorize:

/**
 * Determine if the user is authorized to make this request.
 *
 * @return bool
 */
public function authorize()
{
    return true;
}

Puede escribir a máquina las dependencias que necesite dentro de la firma del método authorize. Se resolverán automáticamente a través del Contenedor de servicio de Laravel

Personalizar los mensajes de error

Usted puede personalizar los mensajes de error usados en la peitición de formulario sobreescribiendo el método messages. Este método debería retornar una matriz de pares de atributos / reglas 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',
    ];
}

Personalizar los atributos de validación

Si desea que la parte ":attribute" de su mensaje de validación se sustituya por un nombre de atributo personalizado, puede especificar los nombres personalizados anulando el método "attributes". Este método debería devolver una matriz de pares de atributos/nombres:

/**
 * Get custom attributes for validator errors.
 *
 * @return array
 */
public function attributes()
{
    return [
        'email' => 'email address',
    ];
}

Preparar la entrada para la validación

Si necesita sanear algún dato de la solicitud antes de aplicar sus reglas de validación, puede utilizar 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),
    ]);
}

# Crear validadores manuales

Si no desea utilizar el método validate dentro de una petición, usted podría crear manualmente, una instancia del validador utilizando el facade Validator. El método make del facade genera una nueva instancia de validator:

<?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 a validar. El segundo argumento es la regla de validación que debería ser aplicada a los datos.

Después de comprobar si la solicitud de validación falló, usted puede usar el método withErrors para flash los mensajes de error en la sesión. Cuando se usa ese método, la variable $errors será compartida automáticamente con sus vistas después de la redirección, permitiéndole mostrarlos fácilmente de nuevo al usuario. El método withErrors acepta un objeto validator, un MessageBag o una matriz de PHP.

Redirección Automática

Si desea crear una instancia del validador de manera manual y aun así aprovechar el re-direccionamiento automático ofrecido por el método validate de las peticiones, puede llamar el método validate en la instancia de tipo validator. De tal manera que si la validación falla, el usuario automáticamente sera redirigido, o en caso de que sea una petición AJAX, se retornara una respuesta en 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');

Nombrar a los Error Bags

Si se tiene múltiples formularios en una sola pagina, es posible querer darle nombre a los errores de MessageBag, lo que le permite recuperar los mensajes de error para un formulario específico. Esto se hace pasando un nombre como segundo argumento del método withErrors:

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

Se puede acceder al nombre de la instancia de MessageBag desde la variable $errors:

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

Hook después de la validación

El validador también permite adjuntar callbacks para que se ejecuten después de que la validación se haya completado. Esto le permite realizar fácilmente una validación adicional e incluso agregar más mensajes de error a la colección de mensajes. Para usarlo, se utiliza el método after en una instancia del validador:

$validator = Validator::make(...);

$validator->after(function ($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add('field', 'Something is wrong with this field!');
    }
});

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

# Gestionar mensajes de error

Después de llamar al método errors en una instancia Validator, se recibirá una instancia de Illuminate\Support\MessageBag, que tiene una variedad de métodos convenientes para trabajar con los mensajes de error. La variable $errors se encuentra disponible en todas las vista como una instancia de la clase MessageBag.

Recuperar el primer mensaje de error para un campo

Para recuperar el primer mensaje de error de un campo se utiliza el método first:

$errors = $validator->errors();

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

Recuperar todos los mensajes de error para un campo

Si se desea recuperar un array de todos los mensajes para un campo determinado, se utiliza el método get:

foreach ($errors->get('email') as $message) {
    //
}

Si está validando un campo de formulario del tipo array, se pueden recuperar todos los mensajes para cada uno de los elementos del mismo utilizando el carácter *:

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

Recuperar los mensajes de error para todos los campos

Para recuperar todos los mensajes de error se utiliza el método all:

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

Verificar si existen mensajes para un campo

El método has determinara si existe algún mensaje de error para el campo determinado:

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

Mensajes de error personalizados

Si es necesario, se pueden personalizar los mensajes de error de las validaciones en lugar de mostrar los que vienen por defecto. Hay varias maneras de especificar mensajes personalizados. La primera, es pasar los mensajes como tercer argumento del método Validator::make:

$messages = [
    'required' => 'The :attribute field is required.',
];

$validator = Validator::make($input, $rules, $messages);

En el ejemplo, se utiliza el place-holder :attribute que es reemplazado por el nombre del campo que se esta validando. Se pueden utilizar otros tipos de place-holders 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',
];

Especificar un mensaje de personalizado para un atributo

Cuando se necesita, es posible personalizar un mensaje de error para un campo especifico. Se puede utilizar la notación "dot" o por "puntos". Se indica el nombre del atributo primero, seguido de la regla de validación:

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

Especificar un mensaje personalizado en los archivos de lenguaje

En la mayoría de los casos, probablemente quiera especificar el mensaje personalizado en el archivo de lenguaje en lugar de pasarlo directamente al Validator. Para hacerlo, se deben agregar los mensajes dentro del array custom del archivo de lenguaje ubicado en resources/lang/xx/validation.php.

'custom' => [
    'email' => [
        'required' => 'We need to know your e-mail address!',
    ],
],

Especificar un atributo personalizado en los archivos de lenguaje

Si se desea cambiar la porción del mensaje de la validación correspondiente a :attribute para reemplazarlo con un nombre de atributo personalizado, se puede especificar el mismo en el array attributes del archivo de lenguaje resources/lang/xx/validation.php:

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

También puedes pasar los atributos personalizados como cuarto argumento al método Validator::make:

$customAttributes = [
    'email' => 'email address',
];

$validator = Validator::make($input, $rules, $messages, $customAttributes);

Especificación de valores personalizados en los archivos de idioma

A veces puede necesitar que la parte :value de su mensaje de validación sea reemplazada por una representación personalizada del valor. Por ejemplo, considere 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:

El campo del número de la tarjeta de crédito es obligatorio cuando el tipo de pago es cc..

En lugar de mostrar cc como valor del tipo de pago, puede especificar una representación de valor personalizado en su archivo de lenguaje de validacion definiendo un array de valores:

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

accepted

El campo de validación debe ser "sí", "en", "1" o "verdadero". Esto es útil para validar la aceptación de las "Condiciones de servicio".

active_url

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

after:date

El campo a validar debe contener un valor posterior a una fecha concreta. Las fechas se pasarán a la función de PHP strtotime:

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

En lugar de pasar una fecha para ser evaluada por strtotime, se puede especificar otro campo con el que comparar la fecha:

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

after_or_equal:date

El campo que se valide debe ser un valor posterior o igual a la fecha indicada. Para más información, véase la regla after.

alpha

El campo que se valide debe ser totalmente de caracteres alfabéticos.

alpha_dash

El campo que se valida puede tener caracteres alfanuméricos, así como guiones y subrayados.

alpha_num

El campo que se valide debe ser totalmente de caracteres alfanuméricos.

array

El campo a validar debe ser un array PHP.

bail

Dejar de ejecutar las reglas de validación después del primer fallo de validación.

before:date

El campo que se valide debe ser un valor anterior a la fecha indicada. Las fechas se pasarán a la función strtotime. Además, al igual que la regla after, el nombre de otro campo en validación puede suministrarse como valor de date.

before_or_equal:date

El campo que se valide debe ser un valor anterior o igual a la fecha dada. Las fechas se pasarán a la función strtotime de PHP. Además, al igual que la regla after, el nombre de otro campo en validación puede suministrarse como valor de date.

between:min,max

El campo que se valide debe tener un tamaño entre el mínimo y el máximo dados. Las cadenas, los números, las matrices y los archivos se evalúan de la misma manera que la regla size.

boolean

El campo bajo validación debe ser capaz de ser lanzado como un booleano. Las entradas aceptadas son true, false, 1, 0, "1", y "0".

confirmed

El campo bajo validación debe tener un campo coincidente de foo_confirmation. Por ejemplo, si el campo bajo validación es password, un campo correspondiente de password_confirmation debe estar presente en la entrada.

date

El campo que se valide debe ser una fecha válida y no relativa según la función PHP strtotime.

date_equals:date

El campo de la validación debe ser igual a la fecha dada. Las fechas se pasarán a la función de PHP strtotime.

date_format:format

The field under validation must match the given format. You should use either "date" o "date_format", no ambos. Esta regla de validación soporta todos los formatos soportados por la clase "DateTime" de PHP.

different:field

El campo a validar debe contener un valor diferente a field.

digits:value

El campo a validar debe ser numérico y una longitud exacta de value.

digits_between:min,max

El campo que se valide debe ser numérico y debe tener una longitud comprendida entre el min y el max dados.

dimensions

El archivo bajo validación debe ser una imagen que cumpla con las restricciones de dimensión especificadas dentro los parámetros de la regla:

'avatar' => 'dimensions:min_width=100,min_height=200'

Las restricciones disponibles son: min_widthmax_widthmin_heightmax_heightwidthheightratio.

El ratio debe representarse como el ancho dividido por la altura. Esto puede especificarse mediante una declaración como 3/2 o un flotante como 1.5:

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

Dado que esta regla requiere varios argumentos, se puede utilizar el método Rule::dimensions para construir la regla con fluidez:

use Illuminate\Validation\Rule;

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

distinct

Cuando se trabaja con arrays, el campo a validar no debe tener valores duplicados.

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

email

El campo de validación debe tener el formato de una dirección de correo electrónico. Bajo el capó, esta regla de validación hace uso del paquete egulias/email-validator de correo electrónico para validar la dirección de correo electrónico. Por defecto se aplica el validador RFCValidation, pero también se pueden aplicar otros estilos de validación:

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

En el ejemplo anterior se aplicarán las validaciones RFCValidationDNSCheckValidation. Aquí hay una lista completa de estilos de validación que puede aplicar:

  • rfc: RFCValidation
  • strict: NoRFCWarningsValidation
  • dns: DNSCheckValidation
  • spoof: SpoofCheckValidation
  • filter: FilterEmailValidation

El validador "filter", que usa la función filter_var de PHP bajo el capó, se envía con Laravel y es el comportamiento pre-5.8 de Laravel. Los validadores dns y spoof requieren la extensión intl de PHP.

ends_with:foo,bar,...

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

exclude_if:anotherfield,value

El campo sometido a validación se excluirá de los datos de la solicitud devueltos por los métodos validate y "validated" si el campo de otro campo es igual al valor.

exclude_unless:anotherfield,value

The field under validation will be excluded from the request data returned by the validate y validated a menos que el campo de otro campo sea igual a su valor.

exists:table,column

El campo bajo validación debe existir en una tabla de base de datos determinada.

Uso básico de la regla exists

'state' => 'exists:states'

Si no se especifica la opción column, se utilizará el nombre del campo.

Especificar un nombre de columna personalizado

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

Ocasionalmente, se puede necesitar especificar la conexión a base de datos a usar para la query de exists. Esto se puede lograr colocando antes del nombre de la tabla el nombre de la conexión, utilizando la sintaxis "dot" o por "punto":

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

En lugar de especificar el nombre de la tabla directamente, se puede especificar el modelo elocuente que debe utilizarse para determinar el nombre de la tabla:

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

Si se desea personalizar la consulta que se ejecuta con la regla de validación, se puede usar la clase Rule para definir la regla. En el ejemplo, se especifican las reglas de validación como un array en lugar de utilizar 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 cargado con éxito.

filled

El campo de validación no debe estar vacío cuando esté presente.

gt:field

El campo que se valida debe ser mayor que el campo dado. Los dos campos deben ser del mismo tipo. Las cadenas, los números, las matrices y los archivos se evalúan utilizando las mismas convenciones que la regla size.

gte:field

El campo que se valide debe ser mayor o igual al campo dado. Los dos campos deben ser del mismo tipo. Las cadenas, los números, las matrices 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 campo a validar debe incluir alguno de los valores listados. Como esta regla a menudo requiere el implode de un arrayRule::in puede usarse para construir la regla con fluidez:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'zones' => [
        'required',
        Rule::in(['first-zone', 'second-zone']),
    ],
]);

in_array:anotherfield.*

En el campo a validar debe existir valores en anotherfield.

integer

El campo a validar debe ser un entero.

Esta regla de validación no verifica que la entrada sea del tipo de variable "integer", sólo que la entrada es una cadena o valor numérico que contiene un entero.

ip

El campo de validación debe ser una dirección IP.

ipv4

El campo a validar debe contener una dirección IPv4.

ipv6

El campo a validar debe contener una dirección IPv6.

json

El campo a validar debe contener una cadena JSON válida.

lt:field

El campo que se valida debe ser menor que el campo dado. Los dos campos deben ser del mismo tipo. Las cadenas, los números, las matrices y los archivos se evalúan utilizando las mismas convenciones que la regla size.

lte:field

El campo que se valide debe ser menor o igual al campo dado. Los dos campos deben ser del mismo tipo. Las cadenas, los números, las matrices y los archivos se evalúan utilizando las mismas convenciones que la regla size.

max:value

El campo a validar debe ser inferior o igual que un máximo value. Cadenas, caracteres numéricos, arrays y archivos se evalúan de la misma forma que la regla size.

mimetypes:text/plain,...

El campo a validar debe coincidir con uno de los tipos de MIME que se declaren:

'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

Para determinar el tipo de 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 a validar debe contener un tipo MIME que corresponda a una de las extensiones listadas.

Uso básico de la regla MIME

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

Aunque solo hay que especificar las extensiones, la regla realmente valida utilizando los tipos MIME del archivo leyendo el contenido del archivo y averiguando su tipo MIME.

La lista completa de tipos MIME y sus extensiones correspondientes se puede encontrar en el siguiente enlace: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

min:value

El campo a validar debe contener un valor mínimo de value. Cadenas de texto, números, arrays y archivos se evalúan del mismo modo que la regla size.

not_in:foo,bar,...

El campo a validar no debe estar incluido dentro del listado de valores. El método Rule::notIn se puede usar para escribir con fluidez la validación:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'toppings' => [
        'required',
        Rule::notIn(['sprinkles', 'cherries']),
    ],
]);

not_regex:pattern

El campo que se valide 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 obedecer al mismo formato requerido por "preg_match" y por lo tanto también incluir delimitadores válidos. Por ejemplo: 'email' => 'not_regex:/^.+$/i'.

Nota: When using the regex / not_regex patterns, it may be necessary to specify rules in an array instead of using pipe delimiters, especially if the regular expression contains a pipe character.

nullable

El campo a validar permite valores null. Esto es particularmente útil cuando se validan primitivas, como cadenas y enteros que pueden contener valores null.

numeric

El campo a validar debe ser numérico.

password

El campo de validación debe coincidir con la contraseña del usuario autentificado. Puede especificar un protector de autenticación utilizando el primer parámetro de la regla:

'password' => 'password:api'

present

El campo que se valida debe estar presente en los datos de entrada, pero puede estar vacío.

regex:pattern

El campo que se valide 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 al mismo formato requerido por preg_match y por lo tanto también incluir delimitadores válidos. Por ejemplo: 'email' => 'regex:/^.+@.+$/i'.

Note: Cuando se utilizan los patrones regex / not_regex, puede ser necesario especificar reglas en una matriz en lugar de utilizar delimitadores de tuberías, especialmente si la expresión regular contiene un carácter de tubería.

required

El campo de validación debe estar presente en los datos de entrada y no estar vacío. Un campo se considera "empty" si se cumple una de las siguientes condiciones:

  • El valor es null.
  • El valor es una cadena vacía.
  • El valor es una matriz vacía o un objeto Countable vacío.
  • El valor es un archivo cargado sin ruta.

required_if:anotherfield,value,...

El campo que se valida debe estar presente y no vacío si el campo de otro campo es igual a cualquier valor.

Si desea construir una condición más compleja para la regla required_if,puede utilizar el método Rule::requiredIf. Este método acepta un booleano o un cierre. Cuando se pasa un Closure, éste debe devolver true or false para indicar si el campo bajo validación es requerido:

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 que se valida debe estar presente y no vacío a menos que el campo de otro campo sea igual a cualquier valor.

required_with:foo,bar,...

El campo que se valida debe estar presente y no vacío sólo si alguno de los otros campos especificados está presente.

required_with_all:foo,bar,...

El campo que se valida debe estar presente y no vacío sólo si todos los demás campos especificados están presentes.

required_without:foo,bar,...

El campo que se valide debe estar presente y no vacío sólo cuando no esté presente ninguno de los otros campos especificados.

required_without_all:foo,bar,...

El campo que se valida debe estar presente y no vacío sólo cuando todos los demás campos especificados no están presentes.

same:field

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

size:value

El campo que se valide debe tener un tamaño que coincida con el valor dado. En el caso de los datos de cadena, el valor corresponde al número de caracteres. Para los datos numéricos, el valor corresponde a un valor entero dado (el atributo también debe tener la regla numericinteger). Para una matriz, el tamaño corresponde al count del array. Para los archivos, el tamaño corresponde al tamaño del archivo en kilobytes. Veamos algunos ejemplos:

// Validar que una cadena tiene exactamente 12 caracteres de largo...
'title' => 'size:12';

// Validar que un entero proporcionado es igual a 10...
'seats' => 'integer|size:10';

// Validar que una matriz tiene exactamente 5 elementos...
'tags' => 'array|size:5';

// Validar que un archivo cargado es exactamente 512 kilobytes...
'image' => 'file|size:512';

starts_with:foo,bar,...

El campo que se valida debe comenzar con uno de los valores dados.

string

El campo de validación debe ser una cadena. Si se desea permitir que el campo sea también null, se debe asignar la regla nullable al campo.

timezone

El campo bajo validación debe ser un identificador de zona horaria válido según la función PHP timezone_identifiers_list.

unique:table,column,except,idColumn

El campo que se valida no debe existir dentro de la tabla de la base de datos dada.

Specifying A Custom Table / Column Name:

En lugar de especificar el nombre de la tabla directamente, se puede especificar el modelo elocuente que debe utilizarse para determinar el nombre de la tabla:

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

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

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

Conexión de la base de datos personalizada

Ocasionalmente, puede ser necesario establecer una conexión personalizada para las consultas de la base de datos realizadas por el Validador. Como se ha visto anteriormente, el establecimiento de unique:users como regla de validación utilizará la conexión predeterminada de la base de datos para consultar la base de datos. Para anular esto, especifique la conexión y el nombre de la tabla utilizando la sintaxis "punto":

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

Forcing A Unique Rule To Ignore A Given ID:

A veces, puede desear ignorar una identificación dada durante el control único. Por ejemplo, considere una pantalla de "actualización de perfil" que incluya el nombre del usuario, la dirección de correo electrónico y la ubicación. Probablemente querrá verificar que la dirección de correo electrónico es única. Sin embargo, si el usuario sólo cambia el campo del nombre y no el del correo electrónico, no querrá que se produzca un error de validación porque el usuario ya es el propietario de la dirección de correo electrónico.

Para instruir al validador a ignorar el ID del usuario, usaremos la clase Rule para definir con fluidez la regla. En este ejemplo, también especificaremos las reglas de validación como una matriz 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 debe pasar ninguna solicitud controlada por el usuario al método ignore. En su lugar, sólo debe pasar un ID único generado por el sistema, como un ID de autoincremento o un UUID de una instancia de modelo elocuente. De lo contrario, su 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, puede pasar toda la instancia de modelo. Laravel extraerá automáticamente la clave del modelo:

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

Si su tabla utiliza un nombre de columna de clave primaria que no sea id, puede especificar el nombre de la columna cuando llame al método ignore:

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

Por defecto, la regla unique comprobará la unicidad de la columna que coincide con el nombre del atributo que se está validando. Sin embargo, puede 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:

Se pueden especificar además cláusulas adicionales personalizando la consulta utilizando el método where. Por ejemplo, añadir una cláusula que verifique que el account_id es 1:

'email' => Rule::unique('users')->where(function ($query) {
    return $query->where('account_id', 1);
})

url

El campo a validar debe ser una URL valida.

uuid

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

# Agregar reglas condicionales

Saltar la validación cuando los campos tienen ciertos valores

Puede que ocasionalmente desee no validar un campo determinado si otro campo tiene un valor determinado. Puede hacerlo utilizando la regla de validación exclude_if En este ejemplo, los campos appointment_datedoctor_name no se validarán si el campo has_appointment tiene un valor de false:

$v = Validator::make($data, [
    'has_appointment' => 'required|bool',
    'appointment_date' => 'exclude_if:has_appointment,false|required|date',
    'doctor_name' => 'exclude_if:has_appointment,false|required|string',
]);

Alternativamente, puede utilizar la regla exclude_unless para no validar un campo determinado a menos que otro campo tenga un valor determinado:

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

Validación cuando está presente

En algunos casos, se pueden ejecutar validaciones a campos únicamente si ese campo está presente en los datos de entrada. Para ello, añadir la regla sometimes a la lista de reglas:

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

En el ejemplo anterior, el campo email será validado únicamente si está presente en el array $data.

Si se intenta validar un campo que debe estar siempre presente pero puede estar vacío, revisar Esta nota para campos opcionales

Validación condicional compleja

A veces es necesario agregar reglas de validación basadas en lógica condicional más compleja. Por ejemplo, se puede requerir un campo si otro posee un valor mayor a 100. O, tal vez que un campo posea un valor concreto únicamente cuando otro campo está presente. Añadir estas reglas de validación debería ser sencillo. Primero, crear la instancia Validator con las reglas estáticas que no cambiarán:

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

Supongamos que nuestra aplicación es para coleccionistas de vídeo juegos. Si el coleccionista se registra en la aplicación y posee más de 100 juegos, requeriremos que explique por qué tiene tantos juegos. Por ejemplo, tal vez sea una tienda de reventa de juegos, o quizás simplemente disfruten de la colección. Para añadir condicionalmente este requerimiento, se puede utilizar el método sometimes de la instancia Validator.

$v->sometimes('reason', 'required|max:500', function ($input) {
    return $input->games >= 100;
});

El primer argumento pasado al método sometimes será el nombre del campo a validar de forma condicional. El segundo argumento serán las reglas de este campo. El tercer parámetro será un Closure que retornará true si las reglas deben tenerse en cuenta. Este método hace que crear validaciones condicionales complejas resulte muy sencillo. Se pueden añadir validaciones condicionales para varios campos a la vez:

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

El parámetro $input pasado al Closure será una instancia de Illuminate\Support\Fluent y se puede utilizar para acceder a los datos de entrada y archivos.

# Validación de Arrays

Validar un array basado en campos de un formulario no debería ser complicado. Se puede usar "dot notation" para validar atributos que sean array. Por ejemplo, si la petición HTTP contiene en campo photos[profile], se puede validar de la siguiente forma:

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

También puede validar cada elemento de una matriz. Por ejemplo, para validar que cada correo electrónico en un campo de entrada de una matriz determinada es único, puede hacer lo siguiente:

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

Asimismo, puede utilizar el carácter * al especificar sus mensajes de validación en sus archivos de idioma, lo que facilita el uso de un único mensaje de validación para los campos basados en matrices:

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

# Reglas de validación personalizadas

Usando objetos Rule

Laravel incluye varias reglas de validación muy útiles; sin embargo, se pueden especificar reglas propias. Una de los métodos para registrar las reglas de validación personalizadas es usando los rule objects. Para generar un nuevo rule object, se puede usar el comando make:rule de Artisan. Se usara este comando para generar una regla que verifique que una cadena esté en mayúscula. Laravel ubicara la nueva regla en el directorio app/Rules:

php artisan make:rule Uppercase

Una vez que el objeto ha sido creado, se puede definir su comportamiento. Un rule object contiene dos métodos: passes y message. El método passes recibe el valor del atributo y el nombre, y retorna true o false dependiendo si el valor del atributo es válido o no. El método message retorna el mensaje de error de la validación que debe ser usado cuando la misma falla:

<?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, se puede usar el helper trans desde su método message si desea devolver un mensaje de error desde los archivos de traducció

/**
 * Get the validation error message.
 *
 * @return string
 */
public function message()
{
    return trans('validation.uppercase');
}

Una vez que se ha definido una regla, se puede asociar al validador pasando una instancia del rule object junto a las otras reglas:

use App\Rules\Uppercase;

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

Usando Closures

Si sólo necesita la funcionalidad de una regla personalizada una vez en toda la aplicación, puede utilizar un objeto Closure en lugar de un objeto de regla. El Cierre recibe el nombre del atributo, el valor del atributo y una llamada de devolución de $fail que debería llamarse si la validación falla:

$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 de registro de las reglas de validación personalizadas es utilizar el método extend en la facade del Validator. Utilicemos este método dentro de un servicio de proveedor 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';
        });
    }
}

El cierre del validador personalizado recibe cuatro argumentos: el nombre del $attribute que se valida, el $value del atributo, una matriz de $parameters pasados a la regla, y la instancia Validator.

You may also pass a class and method to the extend method instead of a Closure:

Validator::extend('foo', 'FooValidator@validate');

Definir el mensaje de error

Hay que definir un mensaje de error para la regla personalizada. Se puede hacer o pasando un mensaje concreto en el array o añadiendo una nueva entrada en el archivo de validación de lenguaje. Este mensaje debe incluirse en el primer nivel del array, nunca dentro del array custom, el cual es únicamente para mensajes de error de atributos específicos:

"foo" => "Your input was invalid!",

"accepted" => "The :attribute must be accepted.",

// The rest of the validation error messages...

Cuando se crea una nueva regla de validación, a veces es necesario definir reemplazos personalizados para los mensajes de error. Esto se puede hacer añadiendo un Validator personalizado como se describe a continuación y llamando al método replacer de la facade Validator. Esto se podría incluir en el método boot de un service provider:

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Validator::extend(...);

    Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
        return str_replace(...);
    });
}

Extensiones implicitas

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

$rules = ['name' => 'unique:users,name'];

$input = ['name' => ''];

Validator::make($input, $rules)->passes(); // true

Para que una regla funcione incluso cuando un atributo está vacío, la regla debe implicar que el atributo es necesario. Para crear esa extensión "implícita", utilice el método Validator::extendImplicit():

Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
    return $value == 'foo';
});

Una extensión "implícita" sólo implica que el atributo es necesario. Si realmente invalida un atributo faltante o vacío depende de usted.

Implicit Rule Objects

Si desea que un objeto de regla se ejecute cuando un atributo está vacío, debe implementar la interfaz Illuminate\Contracts\Validation\ImplicitRule. Esta interfaz sirve como una "interfaz de marcador" para el validador; por lo tanto, no contiene ningún método que necesites implementar.