验证器不生效主因是场景未匹配或规则不全:必须同时定义$rule和$scene,json请求需手动解析php://input,自定义规则中禁用input(),推荐统一使用中间件校验。

验证器不生效,八成是场景没对上,或规则没写全。
验证器必须同时定义 $rule 和 $scene
ThinkPHP 6 的 validate() 方法默认只在校验「匹配的场景」时才触发完整规则。光有 $rule 不行,漏掉 $scene 就等于关掉了开关。
- 控制器里调用
$this->validate($data, $rule, $msg, ['scene' => 'login']) - 验证器类中却只写了
protected $rule = [...],没写protected $scene = ['login' => ['username', 'password']] - 或者写了
$scene,但字段名拼错、大小写不一致(比如写成UserName而实际传的是username) - 场景名为空字符串、
null或类型错误(如传了数组),也会跳过校验
JSON 请求必须手动解析 php://input,不能依赖 input()
前端发 Content-Type: application/json,数据在 php://input 流里,input() 默认只读 $_GET/$_POST,根本拿不到 JSON 字段。
- 错误写法:
$this->validate(input(), $rule)→ 拿到空数组,校验永远通过 - 正确做法:先解析
$json = json_decode(file_get_contents('php://input'), true) ?: [],再传给验证器 - 更推荐用门面:
Validate::make($rule, $json)->batch()->check(),避免和$_POST混淆 - 注意:
json_decode失败会返回null,务必加is_array($json)判断,否则check()可能静默失败
自定义规则里别用 input(),改用传入参数或 with()
在验证器的自定义规则闭包或方法中,直接调 input('field') 是错的——它查的还是 $_POST,不是你解析出来的 JSON 数据。
- 比如规则
'mobile' => ['checkSmsCode' => function($value) { $code = input('sms_code'); ... }]→ 这里$code永远为空 - 应改为把整个数据传进去:
with(['data' => $json]),然后在规则里用$this->data['sms_code'] - 或者直接把依赖字段作为参数传入:
'mobile' => 'require|checkSmsCode:' . $json['sms_code'] - 重复调
input()还会多一次请求解析,浪费 CPU,且可能因编码差异拿到乱码
全局校验建议放中间件,别靠控制器手写 validate()
每个控制器都写一遍 $this->validate(...) 容易漏、难维护,尤其混合了表单和 JSON 请求时。
- 统一在
app/middleware.php中注册\think\middleware\ValidateMiddleware::class - 中间件可按
Content-Type自动分流:表单走Request::param(),JSON 走json_decode(file_get_contents('php://input'), true) - 避免在控制器里混用
input()和param(),前者不识别 JSON,后者自动识别但默认不过滤 - 如果用了
param()做过滤,记得显式传filter参数:$this->request->param([], '', 'htmlspecialchars')
场景绑定、数据源、规则上下文这三块最容易串错,尤其是前后端分离项目里 JSON 和表单共存时,一个地方没对齐,整条链路就失效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











