如果要提供給前端作即時表單驗證時,傳統作法是要在提供一組 API 作為驗證返回使用,Laravel Precognition 這個新的 Laravel 套件提供了較為方便的即時驗證,並且不會讓驗證規則同時存在兩份,也與前端框架作了整合,以下將以註冊功能添即時驗證為範例。
前置
配置 Breeze
$ laravel new laravel10
$ cd laravel10
$ composer require laravel/breeze --dev
$ php artisan breeze:install
$ php artisan migrate
$ npm install
$ npm run dev
原本規則
預設配置好之後,原本的規則寫法是送表單型態,也就是說在送出表單當下才會去驗證欄位機制,這邊如果要調整成即時作表單驗證會有兩種作法:
- 前端取得後端驗證規則後以 JS 再寫入一次規則
- 後端提供驗證 API 操作
這邊可以看到前端寫規則的話當需要作欄位驗證調整時就得再調整,規則分散在兩邊; 而後端自行提供驗證 API 操作需要經過一定設計才會讓代碼不會有重複的狀況。
Laravel Precognition
在先前版本中提供了一種新的工具 Precognition 就是用來解決這個煩惱的。
routes/auth.php
添加中間件作為驗證機制
Route::post('register', [RegisteredUserController::class, 'store'])->middleware([HandlePrecognitiveRequests::class]);
Http/Controllers/Auth/RegisteredUserController.php
將 Validation rule 複製- 創建
RegisterRequest
$ php artisan make:request RegisterRequest
- 刪除
authorize
或是改為true
- 添加規則,用於判斷送入與即時驗證 precognitive 要驗證什麼,我這邊僅先用 unique 作範例
return [
'name' => ['required', 'string', 'max:255'],
'email' => [
// 判斷成立 -> 展開陣列到上層陣列
...$this->isPrecognitive() ? ['unique:'.User::class] : ['required', 'string', 'email', 'max:255', 'unique:'.User::class],
],
'password' => ['required', 'confirmed', Password::defaults()],
];
- 調整
RegisteredUserController.php
request 以及 redirect -> response.json,用於後面前端判斷
return response()->json([
'status' => 0,
'message' => 'Registered is successfully.'
]);
- 調整 Register.vue,引入 pkg 和調用 form
$ npm install laravel-precognition-vue
這邊將原本 inertiajs 調用的 form 改為 precognition,並且針對 submit 後 redirect 進行處理:
import { Head, Link } from '@inertiajs/vue3';
import { useForm } from 'laravel-precognition-vue';
const form = useForm('post', route('register'), {
name: '',
email: '',
password: '',
password_confirmation: '',
});
const submit = () => {
form.submit({
onFinish: () => {
form.reset('password', 'password_confirmation');
},
}).then(response => {
if (response.status === 200 && response.data.status === 0) {
window.location.href = '/dashboard';
}
}).catch(error => {
alert(error.response.data.message);
});
};
//...
<TextInput
id="email"
type="email"
class="mt-1 block w-full"
v-model="form.email"
required
autocomplete="username"
@change="form.validate('email')" //添加當 value.change 時調用驗證
/>
小結
當邏輯或是一人專案實作時這個組件可說是相當好用且實際,不需要花多餘的時間進行維護兩套規則或是新建 API,但同時還是有他一定的限制存在,例如前後端的套件耦合較高,當然你也可以不透過他的套件操作:
Precognition: true
Precognition-Validate-Only: email
這個套件主要面向應該是個人或小團隊開發者方便調用,或是團隊對於技術流程和程度都很熟悉調用會是非常方便的工具,另外 precognition 還是持續在調整中,如果需要應用於 production 環境可以再等到下一個版本穩定再考慮採用,先了解其流程加入到自己的工具箱內。