3分鐘短文:Laravel表單驗證的“指揮中心”:FormRequest

程式設計師小助手發表於2020-10-25

引言

上一章我們學習到,Laravel控制器內引入 ValidatesRequests trait,從而使得繼承了基類控制器的類擁有了驗證器的所有方法。

但是無論在控制器內進行驗證,還是前置到路由器內驗證,都會加重這些區域的程式碼重量,特別是對於複雜的驗證邏輯,甚至使得控制器或者路由功能不那麼純粹。

img

那麼有沒有什麼好的設計方法,把資料驗證獨立出來,統一管理,重複利用,不要寫那麼多臃腫的程式碼呢?這就是本文我們重點要介紹的 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 協議》,轉載必須註明作者和本文連結
write-less-do-more-make-you-out-of-door

相關文章