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
  2. 在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)
    );
    }
    }
  3. 在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
  2. 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.'); // 回傳的錯誤訊息(會在這停止)
    }
    }
    }
  3. 在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',
    ]);
    }
    }