tp6验证器必须严格遵循约定:类文件置于app/validate/目录、命名空间为app\validate、类名匹配文件名;自定义规则方法需public且四参数;必须调用scene()和batch()才能正确验证与返回全部错误。

Validate 类不是拿来就用的黑盒,直接 new 一个裸对象或随手丢个 PHP 文件进目录,大概率验证不生效、方法找不到、错误不返回。核心问题不在“会不会写”,而在“类怎么放、规则怎么配、调用怎么对”。
验证器类必须放在 app/validate/ 目录且命名严格匹配
ThinkPHP 6+ 不会自动扫描任意路径下的验证类。你写了个 UserRegister 类,就必须:
- 文件路径是
app/validate/UserRegister.php - 类名是
class UserRegister extends \think\Validate - 命名空间是
namespace app\validate;
多应用模式下(如 app/admin/),还要加前缀:app\admin\validate\UserRegister,否则 new UserRegister() 会报类未找到。别图省事改命名空间或挪文件位置——框架只认这个约定。
自定义验证方法必须是 public 且带四参数
想写手机号唯一性检查?别写 protected function checkMobile($value),TP6 会直接忽略。正确签名是:
public function ruleMobile($value, $rule = '', $data = [], $field = '')
注意四点:
- 方法必须是
public,不能protected或static - 第四个参数
$field是字段名(如'phone'),漏掉会导致$this->fail()失效 - 规则字符串里写
'phone' => 'ruleMobile',不加function:前缀 - 若需传额外参数(如校验是否排除当前用户),用
ruleMobile:123,$rule就是'123'
场景(scene)和批量错误(batch)不是可选项,而是必开开关
没设 scene() 就调 check($data),验证器会拿全部 $rule 字段去比对——哪怕你只提交了 email,它也会报 username 缺失。同理,不调 batch(true) 或 batch(),getError() 只返回第一个失败项,掩盖其他问题。
典型写法:
$validate = new UserRegister();
$result = $validate->scene('register')->batch()->check($data);
if (!$result) {
dump($validate->getError()); // 返回 ['username' => '用户名不能为空', 'email' => '邮箱格式不正确']
}
场景定义写在验证器里:
protected $scene = [
'register' => ['username', 'password', 'email'],
'reset' => ['email', 'captcha']
];
深层数组字段(如 addresses.*.name)要配合通配符和 strict 模式
直接写 'addresses.0.name' => 'require' 是无效的。TP6 默认不解析点号路径。正确方式是:
- 先声明数组类型:
'addresses' => 'array' - 再用通配符:
'addresses.*.name' => 'require|length:2,20' - 确保验证器启用 strict 模式(5.1+ 默认开启,但某些低版本需手动设
$this->strict(true))
如果数据结构是嵌套对象而非数组(如 { "user": { "name": "a" } }),点号写法依然无效,得先用 json_decode($data, true) 转成关联数组再验证。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











