淺談 Laravel Validation

遇見 Laravel 以前,當要驗證使用者輸入的資料時,很多時候會是類似下面的程式碼

[code lang=”php”]
// validate user post content
if (empty($_POST[‘name’]) || mb_strlen($_POST[‘name’]) > 32) {
// validation not passed
}
[/code]

雖然沒什麼問題,但我們並不能一眼就看出這裡驗證了什麼,此外,如果是對 php 不熟的開發者,可能需要查文件才知道這兩個函式的運作機制,但如果換成下方這種寫法,是不是既優雅又好讀呢

[code lang=”php”]
// validation rules
$rules = [
‘name’ => ‘required|string|max:32’,
];
[/code]

此次要介紹的是 Laravel 的 Validation (驗證),適合對 Laravel 有一些基礎的開發者

本篇文章以 Laravel 5.4 為介紹基礎,不同版本之間可能會有差異,如你使用的版本不是 5.4,請記得至官方文件中查看是否有差異喔

簡介

Validation 最主要的用途是用來驗證使用者提交的表單,確認欄位是否已填,格式是否正確等等,當然,你也可以用來驗證 query string,只是目前我沒有這樣用過 XD

用法

Validation 可以直接寫在 Controller 中,也可以使用 Form Requests 來達成,以下將分別做簡單的介紹

Controller

如果表單欄位沒有很多,規則也不複雜,那麼很適合寫在 Controller 中,方便簡單是它的優勢,直接呼叫 validate 就可以進行驗證,驗證失敗時,會自動導向上一頁,只需花費心思在驗證規則即可

[code lang=”php”]
public function store(Request $request)
{
$this->validate($request, [
‘title’ => ‘required|string|max:191’,
‘content’ => ‘required|string|min:50’,
]);

// validation passed
}
[/code]

上面這個範例中,驗證了 title 和 content 這兩個欄位,兩個欄位都是必填且必須是字串的型態,而 title 最長只能 191 個字,content 則需要大於 50 個字

下面這個範例則是驗證多張圖片上傳, images 欄位是必填且必須是陣列,而此陣列中的每個元素都必須是圖片,大小不能超過 1024 kb,只要陣列其中一個元素不符合,驗證就會失敗

[code lang=”php”]
public function store(Request $request)
{
$this->validate($request, [
‘images’ => ‘required|array’,
‘images.*’ => ‘image|max:1024’,
]);

// validation passed
}
[/code]

上面是兩個簡單的範例,主要是讓你快速了解 Laravel 的 Validation 機制,好讓我們能更近一步探索 Form Requests

Form Requests

在真正的服務中,通常表單不會只有幾個欄位,規則也可能很複雜,因此將驗證機制獨立出來寫會是比較推薦的做法,在對 Validation 有基本的了解後,現在要進階一些囉

Form Requests 是將驗證的規則獨立寫在一個檔案中,相關的檔案會存放在 app/Http/Requests 目錄下,如果要新增一個 Form Request,可以透過 artisan cli 來產生

php artisan make:request <name>

e.g., php artisan make:request BlogRequest

產生的檔案中會有兩個 method,分別是 authorize 和 rules

前者是驗證當前 request 是否已授權 ( authorized ),例如此表單需要登入才能提交,那麼就可以在這裡做檢查,亦或是此表單不僅要登入,還要有特定權限才能提交,那麼也可以在這裡做檢查,然而授權這部分通常在 route 就已經檢查完,因此在我過去開發的專案中,這部分都是直接回傳 true

而後者就是驗證規則撰寫的地方,一樣將用幾個例子來舉例

首先,新增和編輯時表單的驗證規則通常會是一樣的,在 Controller 中你可能會透過設置成 class 的 properties 來減少重複的程式碼,但如果是使用 Form Requests,即可優雅地解決這個問題,稍後將會提到

接著,當欄位有 unique 的規則時,就能體會到 Form Requests 的優勢囉

[code lang=”php”]
public function rules()
{
$rules = [
‘title’ => ‘required|string|max:48|unique:blogs,title’,
‘began_at’ => ‘required|date’,
‘ended_at’ => ‘required|date|after:began_at’,
];

if ($this->isMethod(‘PATCH’)) {
$rules[‘title’] .= ‘,’.$this->route(‘id’).’,id’;
}

return $rules;
}
[/code]

上面這個例子中,當請求的方法是 PATCH (更新) 時,會修改 title 欄位的驗證規則,目的是用於排除該資料本身

試想以下情境,你在編輯一筆資料 (示意如下表格),其中 title 的欄位是 unique,而你只更改了 content,那麼驗證時如果沒有排除自己,就一定會驗證失敗,因此會需要上面的更動

id title content
1 laravel The PHP Framework For Web Artisans

當然,在 Controller 中一樣可以做到相同目的,但程式碼就會複雜許多,適當的保持關注點分離會大大提高程式碼的可讀性,也可以讓邏輯分得更清楚

當規則都寫好後,就是要如何使用啦,聰明的你可能已經想到了

[code lang=”php”]
public function store(BlogRequest $request)
{
// validation passed
}
[/code]

沒錯,就是如此優雅,將原本的 Request 替換成你新增的 Form Request 即可,其餘的交給 Laravel 煩惱就好,當進這個 method 時,就代表驗證已經通過,可以放心使用表單資訊囉 (如果你的規則寫的不完善的話,那就…),驗證失敗時也會自動導向上一頁,一切就是如此優雅

而你可能也想到,應對不同狀況的驗證規則已經在 Form Request 處理好,因此更新的部分也一樣的優雅

[code lang=”php”]
public function update(BlogRequest $request, $id)
{
// validation passed
}
[/code]

專注在該專注的地方,其餘的就交給 Laravel 吧 (y)

總結

本篇簡單的介紹了 Laravel 的 Validation (真的是很淺的介紹),規則部分 Laravel 已提供相當多內建的規則可使用,如果你的商業邏輯更加複雜,也可以自訂規則,而如果想更進一步了解 Validation,建議將官方文件詳細看過一次,會非常有幫助,此外,有任何問題也可以留言詢問喔,本篇到此就告一個段落啦!