1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Laravel Precognition(リアルタイムバリデーション)を試してみた

Last updated at Posted at 2023-06-24

Laravel Precognition とは?

バックエンド(Laravel)のバリデーションルールを用いて、フロントエンド(VueやReact)でリアルタイムなバリデーションを実現する機能です。
Laravel 10.x のドキュメントから追加されたようです。

今回は Laravel + Vue の構成で、以下のログインフォームを想定して動作を検証しました。

実装方法

バックエンド側(Laravel)

まず、バリデーションを行うためのフォームリクエストを作成します。

LoginRequest.php
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 にコントローラーの処理をそのまま記述しています。

api.php
use App\Http\Requests\LoginRequest;

Route::post('/login', function (LoginRequest $request) {
    // コントローラーの処理
});

最後に、HandlePrecognitiveRequests ミドルウェアを指定します。
バックエンド側はこれだけで準備完了です。

api.php
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 のリクエスト(リアルタイムバリデーション)かどうかを判別しているようです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?