??Validator 驗證器 和 常用方法

v1.2.11
版本
2025-07-21
版本更新時間
83
安裝
11
star
Jeckleee/Tools
一個 PHP 數(shù)據(jù)驗證和工具庫,提供符合直覺的鏈式調(diào)用驗證器,讓數(shù)據(jù)驗證變得簡單高效。
主要特性
- 數(shù)據(jù)驗證 : 提供符合直覺的驗證器,使用鏈式調(diào)用添加規(guī)則,方便記憶和使用
- 常用工具函數(shù) : 封裝了一些常用的數(shù)據(jù)處理方法
- 支持多種驗證方式 : 批量驗證、單字段驗證、變量驗證
- 靈活的配置 : 支持自定義異常、錯誤碼、錯誤返回模式
- 豐富的驗證規(guī)則 : 覆蓋大部分常用驗證場景
- 框架兼容 : 可在 Laravel、Webman、ThinkPHP 等主流 PHP 框架中直接使用
安裝
composer require jeckleee/tools
配置
// 配置文件: config/plugin/jeckleee/tools/app.php
return [
'enable' => true,
// 定義驗證失敗以后拋出的異常, webman 框架建議使用 BusinessException::class
'exception' => Exception::class,
// 定義驗證失敗的錯誤碼
'exception_code' => 500,
// 驗證失敗錯誤如何返回(immediate,collective)
// immediate: 立即返回, 只要驗證出現(xiàn)錯誤, 立即拋出當前錯誤字段的異常信息, 不再驗證剩余的字段
// collective: 集中返回, 驗證全部字段, 收集所有異常, 驗證結(jié)束后在異常 $e->getMessage() 中返回錯誤字段的列表, json 字符串形式
'error_return_mode' => 'immediate', // 只支持 immediate 和 collective,其他值會拋異常
];
驗證規(guī)則總覽
驗證規(guī)則 | 說明 | 參數(shù)示例 |
---|---|---|
基礎(chǔ)驗證 | ||
required |
字段必填,可設置一個默認值 | required('默認值') |
ifExisted |
字段存在時才驗證,否則跳過 | ifExisted() |
requiredWith |
當指定字段存在且不為空時,當前字段必填 | requiredWith('email') |
requiredWithout |
當指定字段不存在或為空時,當前字段必填 | requiredWithout('phone') |
same |
當前字段值必須與指定字段值相同 | same('password') |
different |
當前字段值必須與指定字段值不同 | different('old_password') |
字符串驗證 | ||
strTrim |
去除字段兩端的空格、制表符、換行符等 | strTrim() |
strLength |
字段的值必須在指定范圍的長度 | strLength(3, 32) |
strStartWith |
字段的值必須以指定的字符串開始 | strStartWith('http') |
strEndWith |
字段的值必須以指定的字符串結(jié)尾 | strEndWith('.com') |
strAlpha |
字段的值只能由字母組成 | strAlpha() |
strAlphaNum |
字段的值只能由字母和數(shù)字組成,true 時必須同時包含字母和數(shù)字 |
strAlphaNum(true) |
strLowercase |
將字段的值轉(zhuǎn)換為小寫 | strLowercase() |
strUppercase |
將字段的值轉(zhuǎn)換為大寫 | strUppercase() |
數(shù)字驗證 | ||
betweenNumber |
字段的值必須在某兩個數(shù)字區(qū)間(含) | betweenNumber(1, 100) |
cmpNumber |
對字段進行比較,允許的符號: >, <, >=, <=, !=, = | cmpNumber('>', 18) |
isNumber |
字段的值必須是數(shù)字(int 或 float,字符串數(shù)字也通過) | isNumber() |
isInt |
字段的值必須是整數(shù)(int 類型或整數(shù)字符串,如 "123" 也通過) | isInt() |
isFloat |
字段的值必須是小數(shù),可限制小數(shù)位數(shù) | isFloat(2) |
數(shù)組驗證 | ||
inArray |
字段的值必須在數(shù)組中 | inArray([1,2,3]) |
notInArray |
字段的值必須不在數(shù)組中 | notInArray(['admin']) |
isArray |
字段的值必須是數(shù)組 | isArray() |
常用格式驗證 | ||
isEmail |
字段的值必須是郵箱 | isEmail() |
isMobile |
字段的值必須是中國大陸手機號 | isMobile() |
isDateFormat |
字段的值必須是指定格式的時間字符串 | isDateFormat('Y-m-d') |
isIdCard |
字段的值必須是中國大陸身份證號 | isIdCard() |
isUrl |
字段的值必須是網(wǎng)址 | isUrl() |
isIp |
字段的值必須是 IP 地址(ipv4 或 ipv6) | isIp('ipv4') |
isBool |
字段的值必須是布爾值 | isBool() |
isJson |
字段的值必須是一個 json 字符串,true 時轉(zhuǎn)為數(shù)組 |
isJson(true) |
isBase64 |
字段的值必須是有效的Base64編碼字符串 | isBase64() |
文件驗證 | ||
isFile |
文件校驗,支持多種格式:<br/>1. 原始 $_FILES 數(shù)組<br/>2. Laravel 的 Illuminate\Http\UploadedFile 對象<br/>3. Webman 的 support\UploadFile 對象<br/>4. ThinkPHP 的 think\file\UploadedFile 對象<br/>常見用法:<br/>- isFile($_FILES, ['jpg','png'], 1024) <br/>- isFile($request->file(), ['pdf'], 2048) <br/>校驗通過無返回值,失敗則拋出異常 |
isFile($_FILES, ['jpg','png'], 1024) |
其他驗證 | ||
withRegex |
使用正則表達式驗證字段 | withRegex('/^[a-z]+$/') |
fun |
使用自定義驗證函數(shù) | fun(function($val){ return $val > 0; }) |
規(guī)則行為詳解與注意事項
- required($def = null)
- 字段必填。若傳遞
$def
,當字段不存在時會自動賦值為$def
并通過校驗。
- 字段必填。若傳遞
- ifExisted()
- 字段存在時才驗證,否則跳過。適合可選字段。
- isInt()
- 接受 int 類型或整數(shù)字符串(如 "123"、"-456" 也通過)。
- isNumber()
- 接受 int、float 及字符串數(shù)字(如 "123"、"12.3")。
- isFloat($decimalPlaces = null)
- 校驗為浮點數(shù),若指定
$decimalPlaces
,則小數(shù)位數(shù)不能超過該值。
- 校驗為浮點數(shù),若指定
- isFile($file, $ext = [], $maxSize_Kb = 500)
- 支持多種文件對象,校驗通過無返回值,失敗則拋出異常。
$file
可為$_FILES
、Laravel/Webman/ThinkPHP 上傳對象。$ext
限制擴展名,空數(shù)組不限制。$maxSize_Kb
最大文件大小,單位 KB,默認 500KB。
- isJson(true)
- 校驗為 json 字符串,
true
時自動轉(zhuǎn)為數(shù)組。
- 校驗為 json 字符串,
- strAlphaNum(true)
- 必須同時包含字母和數(shù)字。
- requiredWith/requiredWithout
- 依賴字段存在/不存在時,當前字段必填。
- fun(callable)
- 傳入自定義函數(shù),返回 true 通過,否則拋出異常。
用法示例
1. 批量驗證表單數(shù)據(jù)
use Jeckleee\Tools\Validator as V;
$post = [
'name' => 'jeckleee',
'password' => '123456',
'password_confirm' => '123456',
'email' => 'jeckleee@qq.com',
'age' => 18,
'avatar' => $_FILES['avatar'] ?? null
];
// 驗證一組數(shù)據(jù)
$data = V::array($post, [
// 基礎(chǔ)驗證
V::field('name')->required()->strTrim()->strLength(3, 32)->verify('請?zhí)顚懻_的用戶名'),
// 密碼驗證
V::field('password')->required()->strLength(6, 20)->verify('密碼長度6-20位'),
V::field('password_confirm')->same('password')->verify('兩次密碼不一致'),
// 郵箱驗證
V::field('email')->required()->isEmail()->verify('請?zhí)顚懻_的郵箱'),
// 年齡驗證(只接受 int 類型)
V::field('age')->required()->isInt()->betweenNumber(1, 120)->verify('請?zhí)顚懻_的年齡'),
// 文件驗證(第一個參數(shù)為 $_FILES,第二個為擴展名數(shù)組,第三個為最大 KB 數(shù))
V::field('avatar')->isFile($_FILES, ['jpg', 'png', 'gif'], 2*1024)->verify('頭像格式或大小不正確'),
// 條件驗證
V::field('phone')->requiredWithout('email')->isMobile()->verify('手機號或郵箱至少填寫一個'),
V::field('email_code')->requiredWith('email')->strLength(4, 6)->verify('郵箱驗證碼必填'),
// 可選字段驗證
V::field('score')->ifExisted()->isInt()->betweenNumber(0, 100)->verify('請?zhí)顚懻_的分數(shù)'),
]);
// $data 包含所有驗證通過的字段
2. 驗證單個字段
// 驗證一個字段
$age = V::one($post, [
V::field('age')->required()->isInt()->betweenNumber(1, 120)->verify('請?zhí)顚懻_的年齡'),
]);
echo $age; // 輸出: 18
3. 驗證變量
// 驗證變量是否正確, 返回 (bool) TRUE or FALSE
$phone = '123456789';
if (V::var($phone)->isMobile()->check()) {
echo '手機號碼正確';
} else {
echo '手機號碼不正確';
}
4. 自定義驗證規(guī)則
// 自定義驗證方法, 只有回調(diào)方法返回 (bool) true 時, 才驗證通過
$data = V::one($post, [
V::field('age')->fun(function ($value) {
return $value >= 18;
})->verify('年齡不能小于18歲'),
]);
5. 條件必填驗證
$data = V::array($input, [
// 當郵箱存在時,驗證碼必填
V::field('email')->required()->isEmail()->verify('郵箱格式錯誤'),
V::field('email_code')->requiredWith('email')->strLength(4, 6)->verify('郵箱驗證碼必填'),
// 當郵箱不存在時,手機號必填
V::field('phone')->requiredWithout('email')->isMobile()->verify('手機號或郵箱至少填寫一個'),
]);
6. 字段值比較驗證
$data = V::array($input, [
// 密碼確認
V::field('password')->required()->strLength(6, 20)->verify('密碼長度6-20位'),
V::field('password_confirm')->same('password')->verify('兩次密碼不一致'),
// 新舊密碼不能相同
V::field('new_password')->required()->different('old_password')->verify('新密碼不能與原密碼相同'),
]);
7. 文件上傳驗證
// 兼容多種文件上傳格式
$data = V::array($request->all(), [
// 原始 $_FILES 格式
V::field('avatar')->isFile($_FILES, ['jpg', 'png', 'gif'], 2*1024)->verify('頭像格式或大小不正確'),
// Laravel 框架
V::field('document')->isFile($request->file(), ['pdf', 'doc', 'docx'], 10*1024)->verify('文檔格式或大小不正確'),
// Webman 框架
V::field('image')->isFile($request->file(), ['jpg', 'png'], 1024)->verify('圖片格式或大小不正確'),
]);
// Laravel 使用示例
public function upload(Request $request)
{
$data = V::array($request->all(), [
V::field('avatar')->isFile($request->file(), ['jpg', 'png'], 2*1024)->verify('頭像格式或大小不正確'),
V::field('document')->isFile($request->file(), ['pdf'], 5*1024)->verify('文檔格式或大小不正確'),
]);
// ....處理文件上傳
}
// Webman 使用示例
public function upload(Request $request)
{
V::array($request->all(), [
V::field('avatar')->isFile($request->file(), ['jpg', 'png'], 2*1024)->verify('頭像格式或大小不正確'),
V::field('document')->isFile($request->file(), ['pdf'], 5*1024)->verify('文檔格式或大小不正確'),
]);
// ...自己處理文件上傳
}
8. JSON 字符串校驗
// 校驗并轉(zhuǎn)為數(shù)組
$data = V::array($post, [
V::field('data')->isJson(true)->verify('數(shù)據(jù)格式錯誤');
]);
9. Base64 編碼校驗
// 校驗Base64編碼字符串
$data = V::array($post, [
V::field('image_data')->isBase64()->verify('圖片數(shù)據(jù)格式錯誤');
]);
10. 浮點數(shù)校驗
// 校驗并限制 2 位小數(shù)
$data = V::array($post, [
V::field('price')->isFloat(2)->verify('價格格式錯誤');
]);
11. 數(shù)字比較
$data = V::array($post, [
V::field('age')->cmpNumber('>', 18)->verify('年齡必須大于18歲');
]);
12. isInt/isNumber/isFloat 區(qū)別示例
$data = V::array($post, [
V::field('a')->isInt()->verify(); // 接受 int 或整數(shù)字符串(如 "123")
V::field('b')->isNumber()->verify(); // 接受 int/float/字符串數(shù)字
V::field('c')->isFloat(2)->verify(); // 浮點數(shù)且最多2位小數(shù)
]);
13. isFile 返回值說明
// isFile對文件校驗時,沒有返回值
V::array($post, [
// 校驗通過無返回,失敗則拋出異常
V::field('avatar')->isFile($_FILES, ['jpg'], 1024)->verify();
]);
// ...自己處理文件上傳
$avatar=$request->file('avatar')->store('uploads/avatar/avatar');
14. 自定義函數(shù)校驗
$data = V::array($post, [
V::field('score')->fun(function($val){ return $val > 60; })->verify('分數(shù)必須大于60');
]);
15. 字符串大小寫轉(zhuǎn)換
$data = V::array($post, [
// 轉(zhuǎn)小寫
V::field('username')->strLowercase()->verify('用戶名轉(zhuǎn)小寫失敗');
// 轉(zhuǎn)大寫
V::field('code')->strUppercase()->verify('驗證碼轉(zhuǎn)大寫失敗');
]);
異常處理
自定義異常和錯誤碼
// 1. 使用配置文件中定義異常和錯誤碼
$data = V::array($post, [
V::field('name')->required()->verify('請?zhí)顚戀~號'),
]);
// 2. 在使用 array() 或者 one() 方法時定義異常和錯誤碼
$data = V::array($post, [
V::field('name')->required()->verify('請?zhí)顚戀~號'),
], MyException::class, 500);
// 3. 在規(guī)則中的 ->verify() 方法中定義的錯誤碼優(yōu)先級最高
$data = V::array($post, [
V::field('name')->required()->verify('請?zhí)顚戀~號', 12001),
V::field('age')->required()->isInt()->betweenNumber(1, 120)->verify('請?zhí)顚懻_的年齡', 12002),
]);
錯誤返回模式
// immediate 模式:立即返回第一個錯誤
$data = V::array($post, $rules, null, null, 'immediate');
// collective 模式:收集所有錯誤后返回
$data = V::array($post, $rules, null, null, 'collective');
error_return_mode
只支持immediate
和collective
,否則會拋出異常。
完整使用示例
use Jeckleee\Tools\Validator as V;
use support\Request;
class UserController extends BaseController
{
public function register(Request $request): \support\Response
{
try {
$input = V::array($request->all(), [
// 基礎(chǔ)信息驗證
V::field('username')->required()->strTrim()->strLength(3, 20)->strAlphaNum()->verify('用戶名格式錯誤'),
V::field('email')->required()->isEmail()->verify('郵箱格式錯誤'),
V::field('phone')->requiredWithout('email')->isMobile()->verify('手機號或郵箱至少填寫一個'),
// 密碼驗證
V::field('password')->required()->strLength(6, 20)->verify('密碼長度6-20位'),
V::field('password_confirm')->same('password')->verify('兩次密碼不一致'),
// 個人信息驗證
V::field('age')->ifExisted()->isInt()->betweenNumber(1, 120)->verify('年齡格式錯誤'),
V::field('avatar')->ifExisted()->isFile($request->file(), ['jpg', 'png'], 1024)->verify('頭像格式或大小錯誤'),
// 自定義驗證
V::field('invite_code')->fun(function($val) {
return strlen($val) === 6 && ctype_alnum($val);
})->verify('邀請碼格式錯誤'),
]);
//需要自己處理處理頭像的上傳...todo
$avatar = $request->file('avatar')->store('uploads/avatar/avatar');
//將頭像地址增加到$input數(shù)據(jù)中
$input['avatar']=$avatar;
// 創(chuàng)建用戶
$user = User::create($input);
return json(['code' => 200, 'msg' => '注冊成功', 'data' => $user]);
} catch (BusinessException $exception) {
return json([
'code' => $exception->getCode() ?: 300,
'msg' => $exception->getMessage(),
'status' => 'error'
]);
}
}
}
工具函數(shù)
除了驗證器,本工具還提供了一些常用的工具函數(shù):
use Jeckleee\Tools\Tool;
// 二維數(shù)組根據(jù)字段綁定到唯一鍵
$users = Tool::arrayBindKey($userList, 'id');
// $users = [1=>['id'=>1,'name'=>'A'], 2=>['id'=>2,'name'=>'B']]
// 二維數(shù)組根據(jù)字段排序
$sortedUsers = Tool::arraySequence($userList, 'age', 'SORT_DESC');
// $sortedUsers = [['id'=>2,'age'=>30], ['id'=>1,'age'=>20]]
// 生成樹形結(jié)構(gòu)
$tree = Tool::generateTree($list, 'id', 'parent_id', 'children');
// 生成隨機字符串
$randomStr = Tool::getRandomString(16);
// 計算日期差
$days = Tool::diffDateDays('2024-01-01', '2024-01-10');
// 字符串脫敏
$masked = Tool::desensitizeString('13812345678', 3, 4);
// 生成 UUID
$uuid = Tool::generateUUID();
工具函數(shù)說明
- Tool::arrayBindKey($arr, $key)
- 作用:將二維數(shù)組按某字段轉(zhuǎn)為以該字段為 key 的關(guān)聯(lián)數(shù)組。
- 示例:
$arr = [['id'=>1,'name'=>'A'], ['id'=>2,'name'=>'B']]; $res = Tool::arrayBindKey($arr, 'id'); // $res = [1=>['id'=>1,'name'=>'A'], 2=>['id'=>2,'name'=>'B']]
- Tool::arraySequence($arr, $field, $sort = 'SORT_DESC')
- 作用:按指定字段排序。
- 示例:
$arr = [['id'=>1,'age'=>20], ['id'=>2,'age'=>18]]; $res = Tool::arraySequence($arr, 'age', 'SORT_ASC'); // $res = [['id'=>2,'age'=>18], ['id'=>1,'age'=>20]]
- Tool::generateTree($list, $id, $pid, $children)
- 作用:生成樹形結(jié)構(gòu)。
- Tool::getRandomString($len)
- 作用:生成指定長度的隨機字符串。
- Tool::diffDateDays($date1, $date2)
- 作用:計算兩個日期相差天數(shù)。
- Tool::desensitizeString($str, $start, $end)
- 作用:字符串脫敏。
- Tool::generateUUID()
- 作用:生成 UUID。
注意事項
- 驗證規(guī)則順序:建議將
required
規(guī)則放在最前面,避免對空值進行不必要的驗證。 - 錯誤消息:可以為每個規(guī)則自定義錯誤消息,提高用戶體驗。
- 性能考慮:使用
ifExisted
規(guī)則可以避免對不存在字段的驗證。 - 文件驗證:文件驗證支持多種格式:
- 原始
$_FILES
數(shù)組格式 - Laravel 的
Illuminate\Http\UploadedFile
對象 - Webman 的
support\UploadFile
對象 - ThinkPHP 的
think\file\UploadedFile
對象
- 原始
- 條件驗證:合理使用
requiredWith
和requiredWithout
可以處理復雜的表單邏輯。 - isInt/isNumber 區(qū)別:
isInt
接受 int 類型 和 字符串整數(shù) ;isNumber
可接受字符串數(shù)字 和 浮點數(shù)字符串。 - isFloat:可限制小數(shù)位數(shù)。
- isJson:
true
時自動轉(zhuǎn)為數(shù)組。 - 框架兼容性:可在 Laravel、Webman、ThinkPHP 等框架中使用。
- 配置函數(shù)依賴:如需自定義配置,需保證
config()
函數(shù)可用。
貢獻
歡迎提交 Issue 和 Pull Request 來完善這個工具!
許可證
MIT License