验证类应放在app/validate/目录下,类名与文件名一致且继承think\Validate,命名空间为app\validate;多应用模式需匹配应用前缀;scene()控制字段参与验证,batch(true)可返回全部错误。

验证类该放在哪?别放app/common里
ThinkPHP 6+ 的验证类默认走 think\Validate,但自定义类不是随便丢个 PHP 文件就能被识别的。放错位置会导致 Class not found 或验证器始终走默认逻辑。
正确路径是:app/validate/ 下新建 PHP 文件(如 UserRegister.php),类名必须与文件名一致,且继承 think\Validate;同时确保命名空间为 app\validate。
- 不要放在
app/common/或app/library/—— 框架不会自动扫描这些目录下的验证类 - 如果用了多应用模式,注意命名空间前缀可能是
app\api\validate\这类,需和实际应用目录对齐 - 类里不写
protected $rule = [...]也能运行,但推荐集中定义,避免在控制器里拼数组
scene() 不只是分场景,它决定字段是否参与验证
很多人以为 scene() 就是切几组规则,其实它直接控制「哪些字段会被检查」。没进 scene 的字段,即使写了 rule、message,也会被跳过。
比如注册时要校验 password 和 confirm_password,但编辑资料时不校验密码,就必须用 scene 隔离:
class UserRegister extends Validate
{
protected $rule = [
'username' => 'require|alphaNum|length:3,16',
'password' => 'require|length:6,20',
'confirm_password' => 'require|confirm:password',
];
protected $scene = [
'register' => ['username', 'password', 'confirm_password'],
'edit' => ['username'],
];
}
- 调用时必须显式指定:
$validate->scene('register')->check($data),否则默认用全部 rule 字段 - scene 数组里的键名会成为验证入口标识,别用数字索引(如
[0 => 'username']) - 如果某个字段只在部分场景有额外规则(比如邮箱在注册时 require,编辑时 optional),要用
append()或重写getSceneRule()
自定义验证方法必须声明为 public 且带 $value 参数
写了个 checkMobile() 却一直报 method not exists?大概率是函数没设成 public,或者参数签名不对。
ThinkPHP 调用自定义方法时,固定传入三个参数:$value(当前字段值)、$rule(规则值,如 checkMobile:138 中的 138)、$data(整个数据集)。少一个或类型不对都会失败。
- 函数必须是
public function checkMobile($value, $rule = '', $data = []),不能是static或private - 返回
true表示通过,其它任何值(包括null、0、空字符串)都算失败 - 别在方法里 throw 异常——框架会捕获并转成验证失败,但容易掩盖真实问题;建议只 return false + 写日志
- 如果需要复用逻辑(比如多个验证器都要校验身份证),把方法抽到 trait,再 use 进验证类
验证失败后 $validate->getError() 返回的是第一个错误,不是全部
用户填了 5 个错字段,但提示只看到「用户名格式错误」,后面几个全被吞了——这是默认行为,不是 bug。
ThinkPHP 默认只返回第一个触发失败的字段错误信息。想一次性反馈所有问题,得主动开启批量验证:
- 调用前加
$validate->batch(true),之后getError()返回的是数组,格式为['username' => '用户名只能是字母数字', 'email' => '邮箱格式不正确'] - 注意:batch 模式下,
scene()仍生效,但所有在 scene 里的字段都会被扫一遍,不管前面有没有失败 - 如果你用的是 Ajax 提交表单,建议开 batch;如果是传统页面跳转,单条提示更轻量,也更容易定位问题
- 别在验证类构造函数里写
$this->batch(true)—— 它不是属性,不能这样初始化,必须在调用链上显式设置
验证逻辑越往底层封装,越容易忽略 scene 的开关作用和 batch 的触发时机。这两个点不显眼,但线上一出问题,基本就是它们在背锅。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











