Introducción

Laravel proporciona varios enfoques diferentes para validar los datos entrantes de tu aplicación. De forma predeterminada, la clase base del controlador de Laravel usa el trait ValidatesRequests el cual proporciona un método conveniente para validar las solicitudes HTTP entrantes con una variedad de poderosas reglas de validación.

Inicio rápido de validación

Para aprender sobre las poderosas características de validación de Laravel, vamos a observar un ejemplo completo validando un formulario y mostrando los mensajes de error devueltos al usuario.

Definiendo las rutas

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

Route::get('post/create', 'PostController@create');

Route::post('post', 'PostController@store');

La ruta GET mostrará un formulario al usuario para crear un nuevo post de blog, mientras que la ruta POST guardará el nuevo post de blog en la base de datos.

Creando el controlador

Luego, vamos a observar un simple controlador que maneja estas rutas. Dejaremos el método store vacío por ahora:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
    * Show the form to create a new blog post.
    *
    * @return Response
    */
    public function create()
    {
        return view('post.create');
    }

    /**
    * Store a new blog post.
    *
    * @param  Request  $request
    * @return Response
    */
    public function store(Request $request)
    {
        // Validate and store the blog post...
    }
}

Escribiendo la lógica de validación

Ahora estamos listos para completar nuestro método store con la lógica para validar el nuevo post de blog. Para hacer esto, usaremos el método validate proporcionado por el objeto Illuminate\Http\Request. Si las reglas de validación pasan, tu código continuará su ejecución normalmente; sin embargo, si la validación falla, se arrojará una excepción y la respuesta de error apropiada será devuelta automáticamente al usuario. En el caso de una solicitud HTTP tradicional, se generará una respuesta de redirección, mientras una respuesta JSON será enviada para las solicitudes AJAX.

Para lograr una mejor comprensión del método validate, regresemos al método store:

/**
* Store a new blog post.
*
* @param  Request  $request
* @return Response
*/
public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // The blog post is valid...
}

Como puedes ver, pasamos las reglas de validación deseadas dentro del método validate. Otra vez, si la validación falla, se generará la respuesta apropiada automáticamente. Si la validación pasa, nuestro controlador continuará la ejecución normalmente.

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

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

Si quieres especificar el paquete de error en el cual los mensajes de error deberían ser puestos, puedes usar el método validateWithBag:

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

Deteniendo en la primera falla de validación

Algunas veces puede que desees detener la ejecución de las reglas de validación sobre un atributo después de la primera falla de validación. Para hacer eso, asigna la regla bail al atributo:

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

En este ejemplo, si la regla unique del atributo title falla, la regla max no será verificada. Las reglas serán validadas en el orden que sean asignadas.

Una observación sobre los atributos anidados

Si tu solicitud HTTP contiene parámetros «anidados», puedes especificarlos en tus reglas de validación usando la sintaxis de «punto»:

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

Mostrando los errores de validación

¿Qué sucede si los parámetros de solicitud entrantes no pasan las reglas de validación dadas? Cómo mencionamos anteriormente, Laravel redirigirá automáticamente al usuario a su ubicación previa. Además, todos los errores de validación serán automáticamente movidos instantáneamente a la sesión.

De nuevo, observa que no tuvimos que enlazar explícitamente los mensajes de error con la vista en nuestra ruta GET. Esto es porque Laravel revisará los errores en la sesión de datos y los enlazará automáticamente a la vista si están disponibles. La variable $errors será una instancia de Illuminate\Support\MessageBag. Para mayor información sobre cómo trabajar con este objeto, revisa su documentación.

La variable $errors es enlazada a la vista por el middleware Illuminate\View\Middleware\ShareErrorsFromSession, el cual es proporcionado por el grupo de middleware web. Cuando este middleware se aplique una variable $errors siempre estará disponible en tus vistas, permitiendo que asumas convenientemente que la variable $errors está definida siempre y puede ser usada con seguridad.

Así, en nuestro ejemplo, el usuario será redirigido al método create de nuestro controlador cuando la validación falle, permitiéndonos mostrar los mensajes de error en la vista:

<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- Create Post Form -->

Directiva @error

También puedes usar la directiva @error de Blade para rápidamente comprobar si los mensajes de error de validación existen para un atributo dado. Dentro de una directiva @error, puedes mostrar la variable $message para mostrar el mensaje de error:

<!-- /resources/views/post/create.blade.php -->

<label for="title">Post Title</label>

<input id="title" type="text" class="@error('title') is-invalid @enderror">

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

Una observación sobre los campos opcionales

De forma predeterminada, Laravel incluye los middleware TrimStrings y ConvertEmptyStringsToNull en la pila global de middleware de tu aplicación. Estos middleware son listados en la pila por la clase App\Http\Kernel. Debido a esto, con frecuencia necesitarás marcar tus campos «opcionales» de solicitud como nullable si no quieres que el validador considere los valores null como no válidos. Por ejemplo:

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

En este ejemplo, estamos especificando que el campo publish_at puede que sea o null o una representación de fecha válida. Si el modificador nullable no es agregado a la definición de la regla, el validador consideraría el null como una fecha no válida.

Solicitudes AJAX y validación

En este ejemplo, usamos un formulario tradicional para enviar datos a la aplicación. Sin embargo, muchas aplicaciones usan solicitudes AJAX. Al momento de usar el método validate durante una solicitud AJAX, Laravel no generará una respuesta de redirección. En su lugar, Laravel genera una respuesta JSON que contiene todos los errores de validación. Esta respuesta JSON será enviada con un código de estado HTTP 422.

Validación de solicitud de formulario

Creando solicitudes de formulario (form request)

Para escenarios de validación más complejos, puede que desees crear una «solicitud de formulario (form request)». Las Form Request son clases de solicitud personalizadas que contienen la lógica de validación. Para crear una clase de Form Request, usa el comando de CLI de Artisan make:request:

php artisan make:request StoreBlogPost

La clase generada será colocada en el directorio app/Http/Requests. Si este directorio no existe, será creado cuando ejecutes el comando make:request. Agreguemos unas cuantas reglas de validación al método rules:

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

Puedes declarar el tipo de cualquier dependencia que necesites dentro de la firma del método rules. Se resolverán automáticamente a través del contenedor de servicio de Laravel.

Así que, ¿Cómo son evaluadas las reglas de validación? Todo lo que necesitas hacer es poner la referencia de la solicitud en tu método de controlador. La Form Request entrante es validada antes de que el método de controlador sea ejecutado, lo que significa que no necesitas complicar tu controlador con ninguna lógica de validación:

/**
* Store the incoming blog post.
*
* @param  StoreBlogPost  $request
* @return Response
*/
public function store(StoreBlogPost $request)
{
    // The incoming request is valid...

    // Retrieve the validated input data...
    $validated = $request->validated();
}

Si la validación falla, una respuesta de redirección será generada para enviar al usuario de vuelta a su ubicación previa. Los errores también serán movidos instantáneamente a la sesión de modo que estén disponibles para mostrarlos. Si la solicitud fuese una solicitud AJAX, una respuesta HTTP con un código de estado 422 será devuelta al usuario incluyendo una representación JSON de los errores de validación.

Agregando hooks posteriores a solicitudes de formularios

Si prefieres agregar un hook «posterior» a una Form Request, puedes usar el método withValidator. Este método recibe el validador completamente construido, permitiendo que ejecutes cualquiera de sus métodos antes de que las reglas de validación sean evaluadas realmente:

/**
* Configure the validator instance.
*
* @param  \Illuminate\Validation\Validator  $validator
* @return void
*/
public function withValidator($validator)
{
    $validator->after(function ($validator) {
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });
}

Autorizando solicitudes de formularios

La clase Form Request también contiene un método authorize. Dentro de este método, puedes verificar si el usuario autenticado realmente tiene la autoridad para actualizar un recurso dado. Por ejemplo, puedes determinar si a un usuario le pertenece el comentario del blog que está intentando actualizar

/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
    $comment = Comment::find($this->route('comment'));

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

Dado que todas las form requests extienden de la clase solicitud base (Request) de Laravel, podemos usar el método user para acceder al usuario actualmente autenticado. También observa la llamada al método route en el ejemplo anterior. Este método te otorga acceso a los parámetros de URI definidos en la ruta que es ejecutada, tal como el parámetro {comment} en el ejemplo siguiente:

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

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

Si planeas tener la lógica de autorización en otra parte de tu aplicación, devuelve true desde el método authorize:

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

Puedes declarar el tipo de cualquier dependencia que necesites dentro de la firma del método authorize. Se resolverán automáticamente a través del contenedor de servicio de Laravel.

Personalizando los mensajes de error

Puedes personalizar los mensajes de error usados por el form request al sobrescribir el método messages. Este método debería devolver un arreglo de pares atributo / regla y sus correspondientes mensajes de error:

/**
* Get the error messages for the defined validation rules.
*
* @return array
*/
public function messages()
{
    return [
        'title.required' => 'A title is required',
        'body.required'  => 'A message is required',
    ];
}

Personalizando los atributos de validación

Si desea que la parte :attribute de tu mensaje de validación se reemplace con un nombre de atributo personalizado, puedes especificar los nombres personalizados sobrescribiendo el método attributes. Este método debería devolver un arreglo de pares de atributo / nombre:

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

Preparar datos para validación

Si necesitas limpiar datos de la petición antes de aplicar tus reglas de validación, puedes usar el método prepareForValidation:

use Illuminate\Support\Str;

/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}

Creando validadores manualmente

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

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class PostController extends Controller
{
    /**
    * Store a new blog post.
    *
    * @param  Request  $request
    * @return Response
    */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        if ($validator->fails()) {
            return redirect('post/create')
                        ->withErrors($validator)
                        ->withInput();
        }

        // Store the blog post...
    }
}

El primer argumento pasado al método make son los datos bajo validación. El segundo argumento son las reglas de validación que deberían ser aplicadas a los datos.

Después de verificar si la validación de solicitud falló, puedes usar el método withErrors para mover instantáneamente los mensajes de error a la sesión. Al momento de usar este método, la variable $errors será compartida automáticamente con tus vistas después de la redirección, permitiendo que los muestres de vuelta al usuario. El método withErrors acepta un validador, un MessageBag o un array de PHP.

Redirección automática

Si prefieres crear manualmente una instancia del validador pero aún tomar ventaja de la redirección automática ofrecida por el método validate de la solicitud, puedes ejecutar el método validate en una instancia de validador existente. Si la validación falla, el usuario automáticamente será redirigido o, en el caso de una solicitud AJAX, le será devuelta una respuesta JSON:

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

Paquetes de errores con nombres

Si tienes múltiples formularios en una sola página, puede que desees nombrar el MessageBag de errores, permitiendo que obtengas los mensajes de error para un formulario específico. Pasa un nombre como segundo argumento a withErrors:

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

Entonces puedes acceder a la instancia de MessageBag nombrada desde la variable $errors:

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

Hook de validación posterior

El validador también permite que adjuntes funciones de retorno (callbacks) para que sean ejecutadas después que se complete la validación. Esto permite que ejecutes fácilmente validación adicional e incluso agregar más mensajes de error a la colección de mensajes. Para empezar, usa el método after en una instancia de validador:

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

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

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

Trabajando con los mensajes de error

Después de ejecutar el método errors en una instancia Validator, recibirás una instancia Illuminate\Support\MessageBag, la cual tiene una variedad de métodos convenientes para trabajar con los mensajes de error. La variable $errors que se hace disponible automáticamente para todas las vistas también es una instancia de la clase MessageBag.

Obteniendo el primer mensaje de error para un campo

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

$errors = $validator->errors();

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

Obteniendo todos los mensajes de error para un campo

Si necesitas obtener un arreglo de todos los mensajes para un campo dado, usa el método get:

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

Si estás validando un campo de formulario de arreglo, puedes obtener todos los mensajes para cada uno de los elementos del arreglo usando el carácter *:

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

Obteniendo todos los mensajes de error para todos los campos

Para obtener un arreglo de todos los mensajes para todos los campos, usa el método all:

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

Determinando si existen mensajes para un campo

El método has puede ser usado para determinar si existe algún mensaje de error para un campo dado:

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

Mensajes de error personalizados

Si es necesario, puedes usar mensajes de error personalizados en vez de los predeterminados. Hay varias formas para especificar mensajes personalizados. Primero, puedes pasar los mensajes personalizados como tercer argumento al método Validator::make:

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

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

En este ejemplo, el marcador :attribute será reemplazado por el nombre real del campo bajo validación. También puedes utilizar otros marcadores en mensajes de validación. Por ejemplo:

$messages = [
    'same'    => 'The :attribute and :other must match.',
    'size'    => 'The :attribute must be exactly :size.',
    'between' => 'The :attribute value :input is not between :min - :max.',
    'in'      => 'The :attribute must be one of the following types: :values',
];

Especificando un mensaje personalizado para un atributo dado

Algunas veces puedes querer especificar un mensaje de error personalizado sólo para un campo específico. Puedes hacer eso usando notación de «punto». Especifica el nombre del atributo al principio, seguido por la regla:

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

Especificando mensajes personalizados en archivos de idiomas

En muchos casos, probablemente especificarás tus mensajes personalizados en un archivo de idioma en lugar de pasarlos directamente al Validator. Para hacer eso, agrega tus mensajes al arreglo custom en el archivo de idioma resources/lang/xx/validation.php:

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

Especificando los atributos personalizados en archivos de idiomas

Si prefieres que la porción :attribute de tu mensaje de validación sea reemplazada con un nombre de atributo personalizado, puedes especificar el nombre personalizado en el arreglo attributes de tu archivo de idioma resources/lang/xx/validation.php:

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

Especificando los valores personalizados en archivos de idiomas

A veces es posible que necesites que la parte :value de tu mensaje de validación sea reemplazada por una representación personalizada del valor. Por ejemplo, considera la siguiente regla que especifica que se requiere un número de tarjeta de crédito si el payment_type tiene un valor de cc:

$request->validate([
    'credit_card_number' => 'required_if:payment_type,cc'
]);

Si esta regla de validación falla, producirá el siguiente mensaje de error:

The credit card number field is required when payment type is cc.

En lugar de mostrar cc como el valor del tipo de pago, puedes especificar una representación de valor personalizada en tu archivo de idioma validation definiendo un arreglo values:

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

Ahora, si la regla de validación falla, producirá el siguiente mensaje:

The credit card number field is required when payment type is credit card.

Reglas de validación disponibles

A continuación se muestra una lista con todas las reglas de validación disponibles y su función:

accepted

El campo bajo validación debe ser yes, on, 1, o true. Esto es útil para validar la aceptación de «Términos de Servicio», por ejemplo.

active_url

El campo bajo validación debe tener un registro A o AAAA válido de acuerdo a la función de PHP dns_get_record. El hostname de la URL proporcionada es extraído usando la función de PHP parse_url antes de ser pasado a dns_get_record.

after:date

El campo bajo validación debe ser un valor después de una fecha dada. Las fechas serán pasadas a la función de PHP strtotime:

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

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

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

after_or_equal:date

El campo bajo validación debe ser un valor después o igual a la fecha dada. Para mayor información, observa la regla after.

alpha

El campo bajo validación debe estar compuesto completamente por caracteres alfabéticos.

alpha_dash

El campo bajo validación puede tener caracteres alfanuméricos, al igual que guiones cortos y guiones largos.

alpha_num

El campo bajo validación debe estar compuesto completamente por caracteres alfanuméricos.

array

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

bail

Detiene la ejecución de las reglas de validación después del primer error de validación.

before:date

El campo bajo validación debe ser un valor que preceda la fecha dada. Las fechas serán pasadas a la función PHP strtotime. Además, como la regla after, el nombre de otro campo bajo validación puede suministrarse como el valor de fecha date.

before_or_equal:date

Este campo bajo validación debe ser un valor que preceda o igual a la fecha dada. Las fechas serán pasadas a la función de PHP strtotime. Además, como la regla after, el nombre de otro campo bajo validación puede suministrarse como el valor de fecha date.

between:min,max

El campo bajo validación debe tener un tamaño entre el min y max dado. Las cadenas, los números, los arreglos y los archivos se evalúan de la misma manera que la regla size.

boolean

El campo bajo validación debe poder ser convertido como un booleano. Las entrada aceptadas son true, false, 1, 0, "1" y "0".

confirmed

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

date

El campo bajo validación debe ser una fecha válida, no relativa, de acuerdo a la función de PHP strtotime.

date_equals:date

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

date_format:format

El campo bajo validación debe coincidir con el formato format dado. Deberías usar date o date_format al momento de validar un campo, no ambos. Esta regla de validación es compatible con todos los formatos compatibles con la clase DateTime de PHP.

different:field

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

digits:value

El campo bajo validación debe ser de tipo numérico y debe tener una longitud exacta de value.

digits_between:min,max

El campo bajo validación debe ser numérico y tener una longitud entre los valores de min y max dados.

dimensions

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

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

Las restricciones disponibles son: min_width, max_width, min_height, max_height, width, height, ratio.

Una restricción ratio debería ser representada como el ancho dividido por la altura. Esto puede ser especificado por una instrucción como 3/2 o en decimal como 1.5:

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

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

use Illuminate\Validation\Rule;

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

distinct

Al momento de trabajar con arreglos, el campo bajo validación no debe tener ningún valor duplicado.

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

email

El campo bajo validación debe estar formateado como una dirección de correo electrónico. Esta validación hace uso del paquete egulias/email-validator para validar la dirección de correo electrónico. Por defecto, el validador RFCValidation es aplicado, pero también puedes aplicar otros estilos de validación:

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

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

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

El validador filter, que hace uso de la función filter_var de PHP, se entrega con Laravel y es un comportamiento anterior a Laravel 5.8. Los validadores dns y spoof requieren la extensión intl de PHP.

ends_with:foo,bar,…

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

exclude_if:anotherfield,value

El campo bajo validación será excluido de los datos de la petición retornados por los métodos validate y validated si el campo anotherfield es igual al valor value.

exclude_unless:anotherfield,value

El campo bajo validación será excluido de los datos de la petición retornados por los métodos validate y validated a menos que anotherfield sea igual a value.

exists:table,column

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

Uso Básico de la Regla Exists

'state' => 'exists:states'

Si la opción column no está especificada, se usará el nombre del campo.

Especificando un Nombre de Columna Personalizado

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

Ocasionalmente, puedes necesitar especificar una conexión de base de datos para que sea usada por la consulta exists. Puedes lograr esto anteponiendo el nombre de la conexión al nombre de la tabla, usando la sintaxis de «punto»:

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

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

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

Si prefieres personalizar la consulta ejecutada por la regla de validación, puedes usar la clase Rule para definir con fluidez la regla. En este ejemplo, también especificaremos las reglas de validación como un arreglo en vez de usar el carácter | para delimitarlas:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::exists('staff')->where(function ($query) {
            $query->where('account_id', 1);
        }),
    ],
]);

file

El campo bajo validación debe ser un archivo que sea cargado exitosamente.

filled

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

gt:field

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

gte:field

El campo bajo validación debe ser mayor o igual que el campo field dado. Los dos campos deben ser del mismo tipo. Las cadenas, los números, los arreglos y los archivos se evalúan utilizando las mismas convenciones que la regla size.

image

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

in:foo,bar,…

El archivo bajo validación debe estar incluido en la lista dada de valores. Debido a que esta regla requiere con frecuencia que hagas implode a un arreglo, el método Rule::in puede ser usado para construir fluidamente la regla:

use Illuminate\Validation\Rule;

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

in_array:anotherfield.*

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

integer

El campo bajo validación debe ser un entero.

Esta regla de validación no verifica que el campo sea del tipo de variable «entero», sólo que el campo sea una cadena o valor numérico que contenga un entero.

ip

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

ipv4

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

ipv6

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

json

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

lt:field

El campo bajo validación debe ser menor que el valor dado por el campo field. Los dos campos deben ser del mismo tipo. Las cadenas, los números, los arreglos y los archivos se evalúan utilizando las mismas convenciones que la regla size.

lte:field

El campo bajo validación debe ser menor o igual que el valor dado por el campo field. Los dos campos deben ser del mismo tipo. Las cadenas, los números, los arreglos y los archivos se evalúan utilizando las mismas convenciones que la regla size.

max:value

El campo bajo validación debe ser menor que o igual a un valor máximo dado por value. Las cadenas, los números, los arreglos y los archivos son evaluados de la misma forma como la regla size.

mimetypes:text/plain,…

El archivo bajo validación debe coincidir con uno de los tipos MIME dados:

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

Para determinar el tipo MIME del archivo cargado, el contenido del archivo será leído y el framework intentará suponer el tipo MIME, el cual puede ser distinto del tipo MIME proporcionado por el cliente.

mimes:foo,bar,…

El archivo bajo validación debe tener un tipo MIME correspondiente a uno con las extensiones listadas.

Uso Básico de la Regla MIME

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

Incluso aunque solamente necesites especificar las extensiones, en realidad esta regla valida contra el tipo MIME del archivo, mediante la lectura del contenido del archivo y adivinando su tipo MIME.

Una lista completa de tipos MIME y sus correspondientes extensiones puede ser encontrada en la siguiente ubicación: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

min:value

El campo bajo validación deben tener un valor mínimo dado por value. Las cadenas, los números, los arreglos y los archivos son evaluados en la misma forma como la regla size.

not_in:foo,bar,…

El campo bajo validación no debe estar incluido en la lista dada de valores. El método Rule::notIn puede ser usado para construir fluidamente la regla:

use Illuminate\Validation\Rule;

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

not_regex:pattern

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

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

Nota: Al usar los patrones regex / not_regex, puede ser necesario especificar reglas en un arreglo en lugar de usar delimitadores de tubería o «pipes», especialmente si la expresión regular contiene un carácter pipe |.

nullable

El campo bajo validación puede ser null. Esto es particularmente útil al momento de validar tipos primitivos tales como cadenas y enteros que pueden contener valores null.

numeric

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

password

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

'password' => 'password:api'

present

El campo bajo validación debe estar presente en los datos de entrada pero puede estar vacío.

regex:pattern

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

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

Nota: Al usar los patrones regex / not_regex, puede ser necesario especificar reglas en un arreglo en lugar de usar delimitadores de tubería o «pipes», especialmente si la expresión regular contiene un carácter pipe |.

required

El campo bajo validación debe estar presente entre los datos entrada y no estar vacío. Un campo es considerado «vacío» si alguna de las siguientes condiciones es cierta:

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

required_if:anotherfield,value,…

El campo bajo validación debe estar presente y no vacío si el campo anotherfield es igual a cualquier valor dado por value.

Si deseas construir una condición más compleja para la regla required_if, puedes usar el método Rule::requiredIf. Este método acepta un valor booleano o un Closure. Cuando se pasa un Closure, éste debe devolver true o false para indicar si el campo bajo validación es obligatorio:

use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => Rule::requiredIf($request->user()->is_admin),
]);

Validator::make($request->all(), [
    'role_id' => Rule::requiredIf(function () use ($request) {
        return $request->user()->is_admin;
    }),
]);

required_unless:anotherfield,value,…

El campo bajo validación debe estar presente y no vacío a menos que el campo anotherfield sea igual a cualquier valor dado por value.

required_with:foo,bar,…

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

required_with_all:foo,bar,…

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

required_without:foo,bar,…

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

required_without_all:foo,bar,…

El campo bajo validación debe estar presente y no vacío solamente cuando todos los demás campos especificados no están presentes.

same:field

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

size:value

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

// Validate that a string is exactly 12 characters long...
'title' => 'size:12';

// Validate that a provided integer equals 10...
'seats' => 'integer|size:10';

// Validate that an array has exactly 5 elements...
'tags' => 'array|size:5';

// Validate that an uploaded file is exactly 512 kilobytes...
'image' => 'file|size:512';

starts_with:foo,bar,…

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

string

El campo bajo validación debe ser una cadena. Si prefieres permitir que el campo también sea null, deberías asignar la regla nullable al campo.

timezone

El campo bajo validación debe ser un identificador de zona horaria válida de acuerdo con la función de PHP timezone_identifiers_list.

unique:table,column,except,idColumn

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

Especificando un nombre de tabla o columna personalizado:

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

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

La opción column puede ser usada para especificar la columna correspondiente al campo en la base de datos. Si la opción column no es especificada, el nombre del campo será usado.

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

Conexión de base de datos personalizada

Ocasionalmente, puedes necesitar establecer una conexión personalizada para las consultas de bases de datos hechas por el validador. Como has visto anteriormente, al establecer unique:users como una regla de validación usará la conexión de base de datos predeterminada en la consulta de base de datos. Para sobrescribir esto, especifica la conexión y el nombre de la tabla usando la sintaxis de «punto»:

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

Forzando una regla unique para ignorar un ID dado:

Algunas veces, puedes desear ignorar un ID dado durante la verificación de unicidad. Por ejemplo, considera una pantalla «update profile» que incluya el nombre del usuario, dirección de correo electrónico y ubicación. Posiblemente, querrás verificar que la dirección de correo electrónico es única. Sin embargo, si el usuario solamente cambia el campo nombre y no el campo con el correo electrónico, no quieres que un error de validación sea lanzado porque el usuario ya es el propietario de la dirección de correo electrónico.

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

use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

Nunca debes pasar ningún input de la solicitud controlado por cualquier usuario en el método ignore. En su lugar, sólo debes pasar un ID único generado por el sistema, como un ID autoincremental o UUID de una instancia de modelo Eloquent. De lo contrario, tu aplicación será vulnerable a un ataque de inyección SQL.

En lugar de pasar el valor de la clave del modelo al método ignore, puedes pasar la instancia completa del modelo. Laravel automáticamente extraerá la clave del modelo:

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

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

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

Por defecto, la regla única verificará la unicidad de la columna que coincide con el nombre del atributo que se valida. Sin embargo, puedes pasar un nombre de columna diferente como segundo argumento al método unique:

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

Agregando cláusulas where adicionales:

También puedes especificar restricciones de consultas adicionales personalizando la consulta mediante el método where. Por ejemplo, agreguemos una restricción que verifique que el account_id es 1:

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

url

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

uuid

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

Agregando reglas condicionalmente

Validando sólo cuando un campo esté presente

En algunas situaciones, puedes desear ejecutar la verificación contra un campo solamente si ese campo está presente en el arreglo de campos. Para conseguir esto rápidamente, agrega la regla sometimes en tu lista:

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

En el ejemplo anterior, el campo email solamente será validado si está presente en el arreglo $data.

Si estás intentando validar un campo que siempre deba estar presente pero puede estar vacío, revisa esta nota sobre campos opcionales

Validación condicional compleja

Algunas veces puedes desear agregar reglas de validación basadas en lógica condicional más compleja. Por ejemplo, puedes desear solicitar un campo dado solamente si otro campo tiene un valor mayor que 100. O, puedes necesitar que dos campos tengan un valor dado solamente cuando otro campo esté presente. Agregar estas reglas de validación no tiene que ser un dolor. Primero, crea una instancia Validator con tus reglas estáticas que nunca cambian:

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

Asumamos que nuestra aplicación web es sobre coleccionistas de juegos. Si un coleccionista de juego se registra con nuestra aplicación y posee más de 100 juegos, queremos que explique porqué posee tantos juegos. Por ejemplo, quizá administre una tienda de reventa de juegos, o puede ser que solo disfrute coleccionar. Para agregar este requerimiento condicionalmente, podemos usar el método sometimes en la instancia Validator:

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

El primer argumento pasado al método sometimes es el nombre del campo que estamos validando condicionalmente. El segundo argumento son las reglas que queremos agregar. Si la Closure pasada como tercer argumento devuelve true, las reglas serán agregadas. Este método hace que sea muy fácil construir validaciones condicionales complejas. Incluso puedes agregar validaciones condicionales para varios campos de una sola vez:

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

El parámetro $input pasado a tu Closure será una instancia de Illuminate\Support\Fluent y puede ser usado para acceder a tus campos y archivos.

Validando arreglos

Validar arreglos basados en campos de entrada de formulario no tiene que ser un dolor. Puedes usar la «notación de punto» para validar atributos dentro de un arreglo. Por ejemplo, si la solicitud HTTP entrante contiene un campo photos[profile], puedes validarlo así:

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

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

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

De igual forma, puedes usar el carácter * al momento de especificar tus mensajes de validación en tus archivos de idiomas, haciendo que sea muy fácil usar un único mensaje de validación para campos basados en arreglos:

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

Reglas de validación personalizadas

Usando objetos de reglas

Laravel proporciona una variedad de reglas de validación útiles; sin embargo, puedes desear especificar algunas propias. Un método para registrar reglas de validación personalizadas es usar objetos de regla. Para generar un nuevo objeto de regla, puedes usar el comando Artisan make:rule. Usemos este comando para generar una regla que verifique que una cadena esté en mayúscula. Laravel colocará la nueva regla en el directorio app/Rules:

php artisan make:rule Uppercase

Una vez que la regla haya sido creada, estaremos listos para definir su comportamiento. Un objeto de regla contiene dos métodos: passes y message. El método passes recibe el nombre y valor del atributo, y debería devolver true o false dependiendo de si el valor de atributo es válido o no. El método message debería devolver el mensaje de error de validación que debería ser usado cuando la validación falle:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    /**
    * Determine if the validation rule passes.
    *
    * @param  string  $attribute
    * @param  mixed  $value
    * @return bool
    */
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    /**
    * Get the validation error message.
    *
    * @return string
    */
    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

Por supuesto, puedes ejecutar el helper trans de tu método message si prefieres devolver un mensaje de error de tus archivos de traducción:

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

Una vez que la regla haya sido definida, puedes adjuntarla a un validador al pasar una instancia del objeto de regla con tus otras reglas de validación:

use App\Rules\Uppercase;

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

Usando closures

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

$validator = Validator::make($request->all(), [
    'title' => [
        'required',
        'max:255',
        function ($attribute, $value, $fail) {
            if ($value === 'foo') {
                $fail($attribute.' is invalid.');
            }
        },
    ],
]);

Usando extensiones

Otro método para registrar reglas de validación personalizadas es usar el método extend en la clase facade Validator. Usemos este método dentro de un proveedor de servicio para registrar una regla de validación personalizada:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class AppServiceProvider extends ServiceProvider
{
    /**
    * Register any application services.
    *
    * @return void
    */
    public function register()
    {
        //
    }

    /**
    * Bootstrap any application services.
    *
    * @return void
    */
    public function boot()
    {
        Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
            return $value == 'foo';
        });
    }
}

La Closure del validador personalizada recibe cuatro argumentos: el nombre del atributo $attribute que está siendo validado, el valor $value del atributo, un arreglo de parámetros $parameters pasado a la regla y la instancia Validator.

También puedes pasar una clase y método al método extend en vez de una Closure:

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

Definiendo el mensaje de error

También necesitarás definir un mensaje de error para tu regla personalizada. Puedes hacer eso usando un arreglo de mensajes personalizados en línea o agregando una entrada en el archivo de idioma de validación. Este mensaje debería ser colocado en el primer nivel del arreglo, no dentro del arreglo custom, el cual es solamente para mensajes de error específicos de atributos:

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

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

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

Al momento de crear una regla de validación personalizada, algunas veces puedes necesitar definir reemplazos de marcadores personalizados para los mensajes de error. Puedes hacerlo creando un Validador personalizado como se describió anteriormente, y luego haciendo una llamada al método replacer en la clase facade Validator. Puedes hacer esto dentro del método boot de un proveedor de servicio:

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

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

Extensiones implícitas

De forma predeterminada, cuando un atributo que está siendo validado no está presente o contiene una cadena vacía, las reglas de validación normales, incluyendo las extensiones personalizadas, no son ejecutadas. Por ejemplo, la regla unique no será ejecutada en una cadena vacía:

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

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

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

Para que una regla se ejecute incluso cuando un atributo esté vacío, la regla debe implicar que el atributo sea obligatorio. Para crear tal extensión «implícita», usa el método Validator::extendImplicit():

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

Una extensión «implícita» solamente implica que el atributo es obligatorio. Si esto realmente invalida un atributo vacío o faltante depende de ti.

Reglas de objetos implícitas

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

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Sesión HTTP - Documentación de Laravel 6 Lección siguiente Manejo de Errores - Documentación de Laravel 6