首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

ThinkPHP 6/8 表單自動驗證完整指南:驗證器類、場景、規則、自定義訊息與最佳實務

     編輯:PHP 相關知識

前言:ThinkPHP 驗證器架構

ThinkPHP 6/8 採用獨立驗證器類 (think\Validate) 取代舊版 Model 內建 $_validate,支援場景、規則管線、自定義驗證器、批次驗證、事件,更符合單一職責原則。

建立驗證器類

<?php
namespace app\validate;

use think\Validate;

class Article extends Validate {
    // 規則定義
    protected $rule = [
        'title'       => 'require|max:100|token',
        'category_id' => 'require|integer|gt:0',
        'content'     => 'require',
        'cover'       => 'file|image|max:2048', // 檔案驗證
        'tags'        => 'array|max:10',
        'status'      => 'in:0,1,2', // 0草稿 1發布 2下架
    ];

    // 自定義訊息
    protected $message = [
        'title.require'       => '文章標題不能為空',
        'title.max'           => '標題長度不能超過 100 字元',
        'title.token'         => '標題包含敏感詞',
        'category_id.require' => '請選擇分類',
        'category_id.integer' => '分類 ID 必須為整數',
        'category_id.gt'      => '分類 ID 必須大於 0',
        'content.require'     => '文章內容不能為空',
        'cover.image'         => '封面必須為圖片檔案',
        'cover.max'           => '封面大小不能超過 2MB',
        'tags.array'          => '標籤格式錯誤',
        'tags.max'            => '標籤最多 10 個',
        'status.in'           => '狀態值不合法',
    ];

    // 場景定義 (僅驗證指定欄位)
    protected $scene = [
        'create'  => ['title', 'category_id', 'content', 'cover', 'tags'],
        'edit'    => ['title', 'category_id', 'content', 'cover', 'tags', 'status'],
        'publish' => ['status'],
        'batch'   => ['title', 'category_id', 'content'],
    ];

    // 自定義驗證方法 (rule 中使用 'token')
    protected function token($value, $rule, $data): bool {
        $forbidden = ['敏感詞1', '敏感詞2'];
        foreach ($forbidden as $w) {
            if (str_contains($value, $w)) return false;
        }
        return true;
    }
}

控制器中使用

<?php
namespace app\controller;

use app\validate\Article;
use think\facade\Validate;
use think\exception\ValidateException;

class ArticleController {
    public function create() {
        $data = request()->post();
        try {
            // 方式一:直接實例化驗證器 (推薦,支援場景)
            $validate = new Article();
            $validate->scene('create')->check($data);
            // 驗證通過,$data 為安全資料
            $article = ArticleModel::create($data);
            return json(['id' => $article->id]);
        } catch (ValidateException $e) {
            return json(['error' => $e->getError()], 422);
        }
    }

    public function batchCreate() {
        $list = request()->post('list/a', []); // 陣列
        // 批次驗證:每筆資料套用 batch 場景
        $validate = new Article();
        $validate->scene('batch');
        if (!$validate->batch()->check($list)) {
            return json(['errors' => $validate->getError()], 422);
        }
        // $list 現為通過驗證的陣列
        ArticleModel::insertAll($list);
        return json(['count' => count($list)]);
    }
}

內建規則速查表

規則說明範例
require欄位必須存在且非空 (0 視為空需用 require|number)'age'=>'require|number'
max:len字串/陣列/檔案長度 ≤ len'title'=>'max:100'
min:len長度 ≥ len'pwd'=>'min:8'
length:min,max長度區間'pwd'=>'length:8,20'
emailEmail 格式'email'=>'email'
mobile中國手機號'phone'=>'mobile'
urlURL 格式'site'=>'url'
date日期格式 (Y-m-d)'birth'=>'date'
alpha純字母'code'=>'alpha'
alphaNum字母數字'username'=>'alphaNum'
integer/float/number型別檢查'age'=>'integer|gt:0'
in:a,b,c值在列表中'status'=>'in:0,1,2'
notin:a,b值不在列表中'role'=>'notin:admin,root'
regex:pattern正則匹配'code'=>'regex:^[A-Z]{3}\d{4}$'
unique:table,column,except,pk資料庫唯一性'email'=>'unique:users,email'
confirm:field與另一欄位相同 (密碼確認)'repassword'=>'confirm:password'
different:field與另一欄位不同'new_pwd'=>'different:password'
file|image|max:size檔案上傳驗證'avatar'=>'file|image|max:1024'
requireIf:field,value條件必填'card_no'=>'requireIf:pay_type,card'
requireWith:field另一欄位存在時必填'b'=>'requireWith:a'

進階技巧

1. 表單請求類 (Form Request) - Laravel 風格

// app/request/ArticleRequest.php
namespace app\request;

use think\facade\Validate;

class ArticleRequest {
    public function create(): array {
        $validate = Validate::make([
            'title' => 'require|max:100',
            'content' => 'require',
        ], [
            'title.require' => '標題必填',
        ]);
        if (!$validate->check(request()->post())) {
            throw new \think\exception\ValidateException($validate->getError());
        }
        return request()->post();
    }
}
// 控制器
public function create(ArticleRequest $request) {
    $data = $request->create(); // 自動驗證、異常拋出
    ArticleModel::create($data);
}

2. 異步驗證 (AJAX 即時檢查)

// 路由: POST /validate/field
public function validateField() {
    $field = request()->post('field');
    $value = request()->post('value');
    $validate = Validate::make([$field => $this->rules[$field] ?? ''], $this->messages);
    $validate->check([$field => $value]);
    return json(['valid' => true, 'message' => $validate->getError()]);
}

3. 多語言訊息

// lang/zh-tw/validate.php
return [
    'title.require' => '標題不可為空',
    'email.email'   => '信箱格式錯誤',
];
// 驗證器自動讀取 lang/{locale}/validate.php

常見錯誤與避坑

錯誤原因解決
驗證不生效未呼叫 check() 或未捕獲 ValidateException確認流程:new Validate -> scene() -> check() -> try/catch
unique 規則報錯資料表/欄位名錯誤、未排除當前主鍵 (編輯時)'email'=>'unique:users,email,{{id}},id' (模板變數)
檔案驗證失敗未設定 enctype="multipart/form-data"、PHP file_uploads=Off檢查表單屬性、php.ini
批次驗證只回傳第一個錯誤未使用 batch() 方法$validate->batch()->check($list)

完整驗證器範例專案 (含單元測試、多語言、自定義規則庫) 見 GitHub。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved