引言
上一章我們學習到,Laravel控制器内引入 ValidatesRequests trait,進而使得繼承了基類控制器的類擁有了驗證器的所有方法。
但是無論在控制器内進行驗證,還是前置到路由器内驗證,都會加重這些區域的代碼重量,特别是對于複雜的驗證邏輯,甚至使得控制器或者路由功能不那麼純粹。

那麼有沒有什麼好的設計方法,把資料驗證獨立出來,統一管理,重複利用,不要寫那麼多臃腫的代碼呢?這就是本文我們重點要介紹的 FormRequest 表單請求類。
代碼時間
聲明一個表單請求類,使用指令行腳手架可以輕松完成:
php artisan make:request CreateCommentRequest
建立的檔案位于 app/Http/Requests/CreateCommentRequest.php。為了與修改後的代碼有個對比,我們把預設的檔案内容貼在下方:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateCommentRequest extends FormRequest
{
public function authorize()
{
return false;
}
public function rules()
{
return [];
}
}
注意表單請求類預設繼承了 FormRequest 類,預設的方法有兩個:
第一個是 authorize 用于驗證是否有權限使用該驗證器,示例中始終傳回 false,也就是說任何調用,都不被允許,系統傳回 403 狀态碼。
第二個方法是 rules,用于傳回一個驗證規則組成的數組。這個規則的寫法,與上一章我們介紹的規則方法毫無二緻。
下面我們根據業務邏輯,首先修改 authorize 方法,滿足以下兩個條件,才允許驗證:
- 必須登入狀态
- 使用者必須釋出過文章
下面是代碼的實作:
public function authorize()
{
$blogPostId = $this->route('blogPost');
if (! auth()->check()) {
return false;
}
$isExisted = BlogPost::where('id', $blogPostId)->exists();
if (! $isExisted) {
return false;
}
return true;
}
大家看到了吧,在驗證器内可以橫向使用模型資料查詢,來進行資料一緻性判斷。其中還有一個潛在的知識點要說一下,就是代碼開頭的那個 $this->route() 方法,其實是用來擷取路由綁定參數的方法。這要求我們在路由注冊裡,有類似下面這樣的條目:
Route::post('blogPosts/{blogPost}', function () { })
使用路由位置參數綁定傳遞的值,可以使用 $this->route()方法讀取,這與 get/post 方法的擷取有所不同,大家要記得區分。
好了,授權做完了,下面該驗證規則上場了,一旦通過驗證的資料進入到驗證環節,就要執行 rules 方法内定義的規則,我們修改代碼如下:
public function rules()
{
return [
'body' => 'required|max:1000'
];
}
這隻是一個示例啊,大家将就看一看,更多驗證規則在文檔或者源碼裡,有詳細的說明。
完成上述的表單請求類之後,就可以在代碼内引入使用了。最簡單的,在路由檔案内使用依賴注入執行個體化該類:
Route::post('blogPosts/{blogPost}/comment', function (App\Http\Requests\CreateCommentRequest $request) {
// 存儲資料
});
這條路由是我們上述代碼中示範位置參數 blogPost 時引入了,我們在執行方法中引入了表單請求類,laravel自動會将請求資料代入到該類内執行驗證。
我們使用 FormRequest 改造驗證方法之後,不僅引入了資源的權限判斷,還把驗證規則獨立出來,可用于獨立維護,或者集中管控,是不是友善多了?
寫在最後
本文用了一個對部落格文章建立評論内容的方法,将驗證規則在 FormRequest 内實作。我們完全可以從最後一個寫作方法中延伸出更多的花樣玩法,大家可以去github借鑒大神的寫法,學習更多技巧。
Happy coding :-)
我是 @程式員小助手 ,專注程式設計知識,圈子動态的IT領域原創作者