引言
上一章我們學習到,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領域原創作者
本作品採用《CC 協議》,轉載必須註明作者和本文連結