¿Cuántas veces has tenido que escribir las mismas reglas de validación tanto en el backend como en el frontend? Es una situación frustrante que genera código duplicado, inconsistencias y más trabajo de mantenimiento. Laravel Precognition resuelve este problema de forma elegante.
¿Qué es Laravel Precognition?
Laravel Precognition permite anticipar el resultado de una petición HTTP futura. En términos prácticos, ejecuta todo el middleware de la ruta y resuelve las dependencias del controlador (incluyendo la validación de Form Requests), pero sin ejecutar el método del controlador.
Esta característica viene incluida en Laravel desde la versión 10, no necesitas instalar ningún paquete adicional en el backend.
Configurando el Backend
El primer paso es añadir el middleware HandlePrecognitiveRequests a las rutas que necesiten validación en tiempo real:
<?php
use App\Http\Requests\StoreUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (StoreUserRequest $request) {
// Tu lógica aquí
})->middleware([HandlePrecognitiveRequests::class]);Tu Form Request permanece exactamente igual:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUserRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'unique:users,email'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
];
}
}Configurando el Frontend con Vue
Instala el paquete de helpers para Vue:
npm install laravel-precognition-vueAhora puedes usar el composable useForm:
<script setup>
import { useForm } from 'laravel-precognition-vue';
const form = useForm('post', '/users', {
name: '',
email: '',
password: '',
password_confirmation: '',
});
const submit = () => form.submit()
.then(response => {
form.reset();
// Redireccionar o mostrar mensaje de éxito
})
.catch(error => {
// Manejar error
});
</script>
<template>
<form @submit.prevent="submit">
<div>
<label for="name">Nombre</label>
<input
id="name"
v-model="form.name"
@change="form.validate('name')"
/>
<span v-if="form.invalid('name')">
{{ form.errors.name }}
</span>
</div>
<div>
<label for="email">Email</label>
<input
id="email"
type="email"
v-model="form.email"
@change="form.validate('email')"
/>
<span v-if="form.invalid('email')">
{{ form.errors.email }}
</span>
</div>
<div>
<label for="password">Contraseña</label>
<input
id="password"
type="password"
v-model="form.password"
@change="form.validate('password')"
/>
<span v-if="form.invalid('password')">
{{ form.errors.password }}
</span>
</div>
<div>
<label for="password_confirmation">Confirmar Contraseña</label>
<input
id="password_confirmation"
type="password"
v-model="form.password_confirmation"
@change="form.validate('password_confirmation')"
/>
</div>
<button type="submit" :disabled="form.processing">
Registrar
</button>
</form>
</template>Con Vue + Inertia
Si usas Inertia, el paquete específico simplifica aún más el código:
npm install laravel-precognition-vue-inertia<script setup>
import { useForm } from 'laravel-precognition-vue-inertia';
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = () => form.submit({
preserveScroll: true,
onSuccess: () => form.reset(),
});
</script>El método submit ya no devuelve una Promise, sino que utilizas los callbacks de Inertia directamente.
Propiedades y Métodos Útiles
El objeto form expone varias propiedades y métodos que facilitan el trabajo:
// Comprobar si un campo es válido o inválido
form.valid('email') // true si el campo es válido
form.invalid('email') // true si el campo tiene errores
// Acceder a los errores
form.errors.email // mensaje de error del campo
// Limpiar errores manualmente
form.forgetError('email')
// Estado del formulario
form.processing // true mientras se envía
form.validating // true mientras valida
// Verificar si el formulario ha sido modificado
form.hasErrors // true si hay errores de validaciónValidando Múltiples Campos
Útil para formularios tipo wizard donde necesitas validar un grupo de campos antes de pasar al siguiente paso:
form.validate({
only: ['name', 'email'],
onSuccess: () => {
// Avanzar al siguiente paso
nextStep();
},
onValidationError: (errors) => {
// Mostrar errores
}
});Manejando Efectos Secundarios
A veces necesitas ajustar la validación según si es una petición precognitiva o no. Esto es común cuando trabajas con archivos:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreDocumentRequest extends FormRequest
{
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'file' => [
// Solo requerido en el envío final
...$this->isPrecognitive() ? [] : ['required'],
'file',
'mimes:pdf,doc,docx',
'max:10240',
],
];
}
}Testing
Laravel incluye helpers para testear endpoints con Precognition:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
public function test_validates_registration_with_precognition(): void
{
$response = $this->withPrecognition()
->post('/users', [
'name' => 'Juan García',
]);
$response->assertSuccessfulPrecognition();
// Confirmar que no se creó el usuario
$this->assertDatabaseMissing('users', [
'name' => 'Juan García',
]);
}
}Cuándo Usar Precognition
Precognition es ideal cuando necesitas validación en tiempo real y trabajas con Vue o React. Si tu stack es Livewire, ya tienes validación en tiempo real de forma nativa. Algunos casos de uso incluyen validar formularios de registro con campos únicos como emails, wizards multi-paso que requieren validación antes de continuar, y formularios complejos donde la experiencia de usuario se beneficia del feedback inmediato.
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción