Laravel Precognition とは?
バックエンド(Laravel)のバリデーションルールを用いて、フロントエンド(VueやReact)でリアルタイムなバリデーションを実現する機能です。
Laravel 10.x のドキュメントから追加されたようです。
今回は Laravel + Vue の構成で、以下のログインフォームを想定して動作を検証しました。

実装方法
バックエンド側(Laravel)
まず、バリデーションを行うためのフォームリクエストを作成します。
use Illuminate\Foundation\Http\FormRequest;
class LoginRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'email' => ['required'],
'password' => ['required', 'string', 'min:8'],
];
}
}
次に、作成したフォームリクエストをコントローラーで指定します。
今回は api.php にコントローラーの処理をそのまま記述しています。
use App\Http\Requests\LoginRequest;
Route::post('/login', function (LoginRequest $request) {
// コントローラーの処理
});
最後に、HandlePrecognitiveRequests
ミドルウェアを指定します。
バックエンド側はこれだけで準備完了です。
use App\Http\Requests\LoginRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/login', function (LoginRequest $request) {
// コントローラーの処理
})->middleware([HandlePrecognitiveRequests::class]);
フロントエンド側(Vue)
まず最初に、laravel-precognition-vue パッケージをインストールします。
npm install laravel-precognition-vue
次に、useForm()
を使用してフォームオブジェクトを作成します。
パラメータには、HTTPメソッド、URL、初期データを指定します。
<script setup>
import { useForm } from "laravel-precognition-vue";
const form = useForm("post", "/api/login", {
email: "",
password: "",
});
</script>
そして、リアルタイムバリデーションを有効にしたい入力項目に対して、change イベントで form.validate()
を指定します。
<input
v-model="form.email"
@change="form.validate('email')"
/>
ちなみに、ログインボタン押下時に実行する submit イベントには form.submit()
を指定します。
<script setup>
const submit = () => form.submit();
</script>
<template>
<form @submit.prevent="submit()">
また、エラーメッセージは errors オブジェクトに格納されるので、表示したい場合は以下のように記述します。
<div v-if="form.invalid('email')">
{{ form.errors.email }}
</div>
以上でフロントエンド側も準備完了です。
動作検証
不正な入力の場合
パスワードの入力欄に不正な入力を行うと、フォーカスが外れると同時にエラーメッセージが表示されました。

change イベントで validate()
が実行されると、useForm()
で指定した内容をリクエストとして送信するようです。

返却されたレスポンスを確認してみると、ステータスは「422 Unprocessable Content」でした。

正しい入力の場合
正しい入力を行うと、エラーメッセージは表示されませんでした。

返却されたレスポンスを確認してみると、ステータスは「204 No Content」でした。

ちなみに、リアルタイムバリデーションのリクエストでは正しい入力だったとしてもコントローラーの処理は実行されません。
validate()
と submit()
は何が違うの?
リアルタイムバリデーションでも、ログインボタン押下時でも、リクエストが送信されるのは同じURLです。どのように判別しているのでしょうか?
form.validate()
→ リアルタイムバリデーション。バリデーションのみでコントローラーの処理は実行しない。
form.submit()
→ ログインボタン押下時。バリデーションの後、コントローラーの処理を実行する。
そこで validate()
が実行されたときのリクエストヘッダーを確認したところ、Precognition の項目がありました。

このヘッダーによって Precognition のリクエスト(リアルタイムバリデーション)かどうかを判別しているようです。