引言
上一章我們學(xué)習(xí)到琳水,Laravel控制器內(nèi)引入 ValidatesRequests trait,從而使得繼承了基類(lèi)控制器的類(lèi)擁有了驗(yàn)證器的所有方法芥吟。
但是無(wú)論在控制器內(nèi)進(jìn)行驗(yàn)證澎灸,還是前置到路由器內(nèi)驗(yàn)證,都會(huì)加重這些區(qū)域的代碼重量顿肺,特別是對(duì)于復(fù)雜的驗(yàn)證邏輯戏溺,甚至使得控制器或者路由功能不那么純粹渣蜗。
那么有沒(méi)有什么好的設(shè)計(jì)方法,把數(shù)據(jù)驗(yàn)證獨(dú)立出來(lái)于购,統(tǒng)一管理袍睡,重復(fù)利用,不要寫(xiě)那么多臃腫的代碼呢肋僧?這就是本文我們重點(diǎn)要介紹的 FormRequest 表單請(qǐng)求類(lèi)斑胜。
代碼時(shí)間
聲明一個(gè)表單請(qǐng)求類(lèi),使用命令行腳手架可以輕松完成:
php artisan make:request CreateCommentRequest
創(chuàng)建的文件位于 app/Http/Requests/CreateCommentRequest.php嫌吠。為了與修改后的代碼有個(gè)對(duì)比止潘,我們把默認(rèn)的文件內(nèi)容貼在下方:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateCommentRequest extends FormRequest
{
public function authorize()
{
return false;
}
public function rules()
{
return [];
}
}
注意表單請(qǐng)求類(lèi)默認(rèn)繼承了 FormRequest 類(lèi),默認(rèn)的方法有兩個(gè):
第一個(gè)是 authorize 用于驗(yàn)證是否有權(quán)限使用該驗(yàn)證器辫诅,示例中始終返回 false凭戴,也就是說(shuō)任何調(diào)用,都不被允許炕矮,系統(tǒng)返回 403 狀態(tài)碼么夫。
第二個(gè)方法是 rules,用于返回一個(gè)驗(yàn)證規(guī)則組成的數(shù)組肤视。這個(gè)規(guī)則的寫(xiě)法档痪,與上一章我們介紹的規(guī)則方法毫無(wú)二致。
下面我們根據(jù)業(yè)務(wù)邏輯邢滑,首先修改 authorize 方法腐螟,滿(mǎn)足以下兩個(gè)條件,才允許驗(yàn)證:
- 必須登錄狀態(tài)
- 用戶(hù)必須發(fā)布過(guò)帖子
下面是代碼的實(shí)現(xiàn):
public function authorize()
{
$blogPostId = $this->route('blogPost');
if (! auth()->check()) {
return false;
}
$isExisted = BlogPost::where('id', $blogPostId)->exists();
if (! $isExisted) {
return false;
}
return true;
}
大家看到了吧困后,在驗(yàn)證器內(nèi)可以橫向使用模型數(shù)據(jù)查詢(xún)乐纸,來(lái)進(jìn)行數(shù)據(jù)一致性判斷。其中還有一個(gè)潛在的知識(shí)點(diǎn)要說(shuō)一下摇予,就是代碼開(kāi)頭的那個(gè) $this->route() 方法汽绢,其實(shí)是用來(lái)獲取路由綁定參數(shù)的方法。這要求我們?cè)诼酚勺?cè)里侧戴,有類(lèi)似下面這樣的條目:
Route::post('blogPosts/{blogPost}', function () { })
使用路由位置參數(shù)綁定傳遞的值宁昭,可以使用 $this->route()方法讀取,這與 get/post 方法的獲取有所不同救鲤,大家要記得區(qū)分久窟。
好了,授權(quán)做完了本缠,下面該驗(yàn)證規(guī)則上場(chǎng)了斥扛,一旦通過(guò)驗(yàn)證的數(shù)據(jù)進(jìn)入到驗(yàn)證環(huán)節(jié),就要執(zhí)行 rules 方法內(nèi)定義的規(guī)則,我們修改代碼如下:
public function rules()
{
return [
'body' => 'required|max:1000'
];
}
這只是一個(gè)示例啊稀颁,大家將就看一看芬失,更多驗(yàn)證規(guī)則在文檔或者源碼里,有詳細(xì)的說(shuō)明匾灶。
完成上述的表單請(qǐng)求類(lèi)之后棱烂,就可以在代碼內(nèi)引入使用了。最簡(jiǎn)單的阶女,在路由文件內(nèi)使用依賴(lài)注入實(shí)例化該類(lèi):
Route::post('blogPosts/{blogPost}/comment', function (App\Http\Requests\CreateCommentRequest $request) {
// 存儲(chǔ)數(shù)據(jù)
});
這條路由是我們上述代碼中演示位置參數(shù) blogPost 時(shí)引入了颊糜,我們?cè)趫?zhí)行方法中引入了表單請(qǐng)求類(lèi),laravel自動(dòng)會(huì)將請(qǐng)求數(shù)據(jù)代入到該類(lèi)內(nèi)執(zhí)行驗(yàn)證秃踩。
我們使用 FormRequest 改造驗(yàn)證方法之后衬鱼,不僅引入了資源的權(quán)限判斷,還把驗(yàn)證規(guī)則獨(dú)立出來(lái)憔杨,可用于獨(dú)立維護(hù)鸟赫,或者集中管控,是不是方便多了消别?
寫(xiě)在最后
本文用了一個(gè)對(duì)博客帖子創(chuàng)建評(píng)論內(nèi)容的方法抛蚤,將驗(yàn)證規(guī)則在 FormRequest 內(nèi)實(shí)現(xiàn)。我們完全可以從最后一個(gè)寫(xiě)作方法中延伸出更多的花樣玩法寻狂,大家可以去github借鑒大神的寫(xiě)法岁经,學(xué)習(xí)更多技巧。
Happy coding :-)
我是@程序員小助手荆虱,專(zhuān)注編程知識(shí)蒿偎,圈子動(dòng)態(tài)的IT領(lǐng)域原創(chuàng)作者