Validator簡單介紹

在Laravel中,Validator是一個驗證器,可以用來驗證使用者輸入的資料是否符合規定。在認識這個之前,很常需要針對請求過來的各欄位資料特別處理,導致專案變大時,重複的驗證方法四散各地,難以維護。而Validator就是為了解決這個問題而生的,它可以將驗證的規則寫在一個地方,並且可以重複使用,讓程式碼更加簡潔。

Validator基本上有分兩種驗證:

以下兩種功能基本上相同,只是第一種自動幫你做了不少事情;第二種則是完全客製化,可以自己定義錯誤行為,但是要自己處理跳轉、錯誤訊息等等。

Request物件中的驗證:

  • 可以直接從request物件中使用驗證方法,並且會自動把request資料帶入驗證,其中第一個參數可以填入各欄位的驗證規則,第二個參數可以填入自訂錯誤訊息,範例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Illuminate\Http\Request;

// rqeuest物件中的validate方法
function index(Request $request)
{
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
], [
'title.required' => '標題必填。',
'title.max' => '標題不能超過30個字',
'body.required' => '內容必填。',
]);
}

  • 基本上是給php原生送表單用的,所以失敗時會自動跳轉回去原本頁面,並且errors寫入閃存session,所以我可以在blade中使用@error('title')來顯示錯誤訊息
  • 假設有相同驗證組合想重複使用,可以創建app\Request\CustomRequest.php,並且在Controller中使用:
  1. 創建CustomRequest:
1
php artisan make:request CustomRequest
  1. 在Controller中使用範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\JsonResponse;
class CustomRequest extends FormRequest
{
/**
* Determine if the user is authorized` to make this request.
*/
// 預設function,定義授權規則
public function authorize(): bool
{
// do something and return true or false
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
// 預設function,定義驗證規則
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:6|confirmed',
];
}

// 預設function,可自行定義錯誤訊息
public function messages()
{
return [
'name.required' => '姓名不能為空。',
'email.required' => '信箱不能為空。',
// 其他自訂錯誤訊息
];
}

// 預設function,驗證失敗時會執行,這邊自定義錯誤時會傳json
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(
response()->json([
'status' => 'error',
'message' => 'Validation failed',
'errors' => $validator->errors(),
], JsonResponse::HTTP_UNPROCESSABLE_ENTITY)
);
}

// 預設function,授權失敗時會執行,這邊自定義錯誤時會傳json
protected function failedAuthorization()
{
throw new HttpResponseException(
response()->json([
'status' => 'error',
'message' => 'Authorization failed',
], JsonResponse::HTTP_UNAUTHORIZED)
);
}
}
  1. 在Controller中使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\CustomRequest;

class UserController extends Controller
{
protected $customService;

public function __construct(
CustomService $customService,
)
{
$this->customService = $customService;
}

// 注入CustomRequest,便會自動驗證,並且失敗時會直接return上面定義的json
function index(CustomRequest $request)
{
}
}

Validator物件自訂驗證:

  • 寫法:
1
2
3
4
5
6
7
8
9
10
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

function index(Request $request)
{
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
], $customMessage);
}
  • 因為都是自訂的,所以不會自動幫你跳轉,錯誤行為都可自行定義,也沒有建議使用在哪裡,只要有驗證都可以使用
  • 如果想建立完全客製驗證物件,個人建立在App\Utilities(可依照需求放不同位置),並以Validator物件實現

自訂驗證規則:

  • 假設我需要個人客製驗證規則(原本laravel定義(required,max...)之外的),我可以在App\Rules中建立規則,並且在需要時使用時直接引用,範例如下:
  1. 建立規則:
1
php artisan make:rule CustomRule
  1. App\Rules\CustomRule.php中撰寫規則:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class CustomRule implements ValidationRule
{
/**
* Run the validation rule.
*
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
// do something
if ($value != 'test') {
$fail('The '.$attribute.' is invalid.'); // 回傳的錯誤訊息(會在這停止)
}
}
}
  1. 在Controller中使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Rules\CustomRule;

class UserController extends Controller
{
function index(Request $request)
{
$validated = $request->validate([
'title' => ['required', new CustomRule], // 直接把規則帶入陣列即可
'body' => 'required',
]);
}
}