tp6验证器必须继承think\validate类,字段名需与数据键严格一致,scene必须显式指定,自定义规则须为public且四参数签名。

验证器类必须继承 think\Validate,不能直接用数组规则硬塞
TP6 的验证逻辑是基于类实例的,所有规则、提示、场景都得绑定在验证器类上。你写一个纯数组(比如 ['name' => 'require'])传给 validate(),它会尝试反射类名,找不到类就报错或静默失效。
常见错误现象:控制器里写 validate(['email' => 'email'])->check($data),结果完全不校验——因为这不是合法的验证器类,框架跳过处理。
- 必须新建 PHP 类,如
app\validate\UserValidate.php - 类要
extends think\Validate,否则rule、message属性不被识别 -
protected $rule是关联数组,键为字段名,值为规则字符串(如'email' => 'require|email') - 字段名必须和
$data数组的键完全一致,大小写、下划线、点号都不能错
required 不校验空字符串,需要组合规则或自定义
原生 required 只判断 isset(),对 ''、'0'、'false' 这类“存在但无效”的值放行。用户提交空昵称、零金额订单时容易绕过。
解决方式不是改框架,而是选对规则组合:
- 要严格非空:用
'nickname' => 'require|alphaNum|min:1',min:1强制至少 1 字符 - 要过滤前后空格再判空:先在控制器用
input('post.nickname', '', 'trim'),再进验证器 - 要支持“0”但拒绝空:自定义规则,签名必须是
public function ruleNonEmpty($value, $rule, $data, $field),返回is_string($value) ? strlen(trim($value)) > 0 : !empty($value)
场景($scene)不配就等于没写,且必须和 check() 调用时匹配
验证器默认只校验 $scene 中声明的字段。哪怕 $rule 写了 20 条,没放进 $scene,调用时又没指定 scene,那整条规则表就闲置了。
典型翻车现场:写了 protected $scene = ['login' => ['username', 'password']],但控制器里调 $validator->check($data) 没带 scene('login'),结果 username 根本不校验。
-
$scene是二维数组:['create' => ['name', 'email'], 'update' => ['name']] - 调用时必须显式指定:
$validator->scene('create')->check($data) - 如果想让某个字段在所有场景都生效,把它加进每个 scene 数组,别指望“默认全开”
- 注意:
$scene仅控制字段白名单,不改变规则内容;字段不在 scene 里,连规则解析这步都跳过
自定义规则必须 public、四参数、不抛异常
在验证器类里写 protected function checkMobile(),然后规则写 'phone' => 'checkMobile',运行时报 Call to undefined method——因为 TP6 的规则反射只找 public 方法。
更隐蔽的问题是签名错一个字:少个参数、顺序颠倒、用了可选参数,默认值写在中间,都会导致 check() 内部调用失败。
- 正确签名:
public function ruleMobile($value, $rule, $data, $field) - 返回
true表示通过,false表示失败;别throw new Exception() - 设错误信息用
$this->error = ':attribute 手机号格式错误',不是return '提示' - 若需全局复用(多个验证器共用),改用
Validator::extend('mobile', [$this, 'ruleMobile']),注册位置必须在验证器初始化阶段(如init()方法内)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











