自定义规则函数必须显式注册,如在init()中调用extend();禁止验证时实时查库,应预加载或缓存;scene需显式声明,字段名须严格匹配;手机号等带参规则推荐闭包注册并解析$rule参数。

自定义规则函数必须显式注册,不能只写方法名
写了 checkIdCard 方法,但在 $rule 里写 'id_card' => 'checkIdCard',运行时报 “method not exists”——ThinkPHP 不会自动扫描 public 方法,必须手动注册别名。
实操建议:
- 函数必须声明为
public,且签名完整:public function checkIdCard($value, $rule = '', $data = [], $field = '') - 在验证器类的
init()或__construct()中调用$this->extend('id_card', 'checkIdCard') -
$rule数组中仍用'id_card'(即 extend 的第一个参数),不是函数名本身 - 别写成
'id_card' => [$this, 'checkIdCard'],这会导致序列化失败,验证器无法复用
手机号等带参数的规则,要用闭包 + 动态解析
想支持不同国家区号(如 isMobile:86、isMobile:852),但直接用内置 regex 规则写死正则,后续改起来麻烦,也不支持传参。
实操建议:
- 在
init()中注册闭包:Validator::extend('isMobile', function($value, $rule) { ... }) -
$rule参数可能是字符串(如'86')或数组(如['86', 'required_prefix']),需自行解析 - 推荐正则用
/^1[3-9]\d{9}$/(纯数字11位),不兼容带空格/横线的“宽松格式”,前端应提前格式化 - 错误提示统一配在
$message里:'isMobile' => ':attribute 必须是有效的中国大陆手机号'
数据库查询类规则必须预加载或加缓存
写 'category_id' => 'callback:checkCategoryExists',而 checkCategoryExists 里直接查库:Db::name('category')->where(...)->find(),并发一上来就卡住,QPS 直接掉一半。
实操建议:
- 禁止在回调里实时查库;更优解是在
__construct()中一次性加载所有合法category_id,存到私有属性(如$this->validCats),回调里只做in_array($value, $this->validCats) - 若数据更新频繁,改用
Cache::remember('valid_category_ids', 600, function () { ... }),缓存 10 分钟 - 绝对不要在验证阶段执行
insert或update,验证不走事务,失败后可能留下脏数据
场景(scene)未定义会导致静默失效
控制器里调 $this->validate($data, 'UserValidate.login'),但验证器没定义 $scene,结果既不报错也不校验,数据直接穿过去了。
实操建议:
-
$scene必须显式声明,哪怕只有一条规则:protected $scene = ['login' => ['username', 'password']] - 字段名必须和
$data数组键名完全一致(大小写、下划线都不能错) - 如果想让某个字段在多个场景共用,别重复写,用
$scene['login'] = array_merge($scene['register'], ['captcha'])合并
init),而验证逻辑一旦涉及 I/O 就得主动规避,不是“能跑通”就行。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











