最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
TP8.0 验证器自定义规则编写全攻略 保姆级
时间:2026-07-10 10:12:47 编辑:袖梨 来源:一聚教程网
ThinkPHP 8.0 中自定义验证规则需通过 init() 方法或控制器动态注册,手机号校验需支持国际区号参数、身份证校验须预加载省份码避免实时查库,场景校验必须正确定义 $scene 属性否则规则失效。
在 ThinkPHP 8.0 中为手机号加国际区号校验、为身份证号做末位校验、为密码强制要求含大小写字母和数字——这些不能靠内置规则解决的业务逻辑,必须写自定义验证规则,否则验证器直接报错或跳过校验。
注册自定义规则的两种入口
方法一:在验证器类的 init() 方法中注册(推荐)
打开 app/validate/UserValidate.php,在 init() 方法里调用 $this->extend(),传入别名和回调函数或方法名字符串。
方法二:在控制器中动态注册
创建验证器实例后,立即调用 $validate->extend(),适用于临时、一次性、不复用的规则,但无法被缓存复用,且无法参与场景(scene)校验。
【别名必须全局唯一】 若两个验证器都注册了 'id_card' 别名,后注册的会覆盖前一个,导致不可预期的校验行为。
写一个带参数的手机号校验规则
第一步:在 UserValidate 类的 init() 方法中注册闭包
$this->extend('isMobile', function($value, $rule) { $prefix = is_string($rule) ? $rule : ($rule[0] ?? '86'); $pattern = match($prefix) { '86' => '/^1[3-9]d{9}$/u', '852' => '/^([2-9]d{7}|[2-9]d{3}-d{4})$/u', default => '/^+' . preg_quote($prefix) . 'd{10,15}$/u'; }; return (bool) preg_match($pattern, $value);});
第二步:在 $rule 中使用带参写法
'mobile' => 'isMobile:86' 或 'mobile' => 'isMobile:852',注意冒号后不要加空格。
第三步:在 $message 中配提示语
'mobile.isMobile' => ':attribute 必须是有效的 :rule 区号手机号',其中 :rule 会自动替换为传入的参数值(如 86)。
这一步操作起来很简单,直接把文件拖进去就行。但若漏掉 u 修饰符,中文或 emoji 输入时正则会匹配失败,且错误无提示,只返回 false。
写一个查库类的身份证校验规则
先在 __construct() 中预加载合法省份码,避免每次验证都查库:
$this->validProvinces = Cache::remember('idcard_provinces', 3600, function () { return Db::name('province_code')->column('code');});
再定义校验方法,签名必须完整:
public function checkIdCard($value, $rule = '', $data = [], $field = '') { if (!is_string($value) || strlen($value) !== 18) { return '身份证长度必须为18位'; } $provinceCode = substr($value, 0, 2) . '00'; if (!in_array($provinceCode, $this->validProvinces)) { return '身份证归属地代码无效'; } // 末位校验略(实际需补全) return true;}
最后在 init() 中注册别名:
$this->extend('id_card', 'checkIdCard');
【禁止在回调里实时查库】 若此处直接写 Db::name('idcard_check')->where(...)->find(),高并发下数据库连接池会迅速耗尽,QPS 断崖式下跌。
验证器中启用场景并绑定规则
① 在验证器类中声明 $scene 属性,例如:
protected $scene = [ 'login' => ['username', 'password'], 'register' => ['username', 'password', 'mobile', 'id_card'],];
② 控制器中调用时指定场景名:
$result = $validate->scene('register')->check($data);
③ 场景字段可叠加额外规则:
protected $scene = [ 'register' => ['username', 'password', 'mobile', 'id_card'],];protected $pattern = [ 'username' => '/^[a-zA-Z][a-zA-Z0-9_]{4,19}$/u',];
若未定义 $scene,调用 scene('xxx') 不会报错,但规则完全不生效,数据直接穿透过去——这个坑没有任何日志提示,只能靠断点确认。
相关文章
- 写实奢华浴室人像 07-21
- 城市峡谷中的霓虹大桥 07-21
- 晨光空灵人像 07-21
- 猫王小黄鸭 07-21
- 日落海滩时尚人像 07-21
- iOS哔咔网页版入口-哔咔漫画iOS网页版入口 07-21