闭包规则中 $value 即当前字段原始值,无需从 $data 中手动获取;$rule 是冒号后参数,$data 为全量数据,scene 不影响 $value 准确性但不裁剪 $data;extend 需在 check 前调用,且 $value 始终真实反映字段值(含 null、空字符串等边界情况)。

验证器里拿不到当前字段值,基本等于规则写废了一半——rule 里的闭包函数必须能访问被验字段的原始值,否则像“密码需不等于旧密码”“用户名不能含邮箱字符”这类逻辑根本没法做。
闭包规则中 $value 就是当前字段值,别手动从 $data 里取
很多人写自定义规则时习惯在闭包里用 $data['field_name'] 去读值,这是错的。ThinkPHP 传入闭包的 $value 参数就是当前正在验证的那个字段的原始值,已经剥离了上下文干扰。
-
$value是字段当前值(比如email字段传进来就是用户填的字符串) -
$rule是规则定义里的冒号后内容(如'checkOldPass:old_password'中的old_password) -
$data是整个待验证数组,仅在需要跨字段比对时才用
错误写法:function($value, $rule, $data) { return $data['password'] === $data['old_password']; }
正确写法:function($value, $rule, $data) { return $value !== $data[$rule]; }(假设规则是 'password'=>'checkOldPass:old_password')
立即学习“PHP免费学习笔记(深入)”;
scene 切换后 $value 仍准确,但 $data 不会自动过滤
场景验证(scene('edit'))只控制哪些字段参与验证,不影响闭包参数传递逻辑——$value 还是那个字段的值,但 $data 仍是全量数据,不会被 scene 自动裁剪。
- 如果你在
edit场景下验证name字段,闭包里$value就是$data['name']的值,不是 null 或空 - 不要指望
$data在场景下只剩被验证字段;需要字段存在性判断时,得自己用isset($data['xxx']) - 场景和动态规则可混用:比如
$validate->scene('reset')->check($data),闭包内逻辑照常执行
批量注册自定义规则时,$value 行为一致,但注意 extend() 的调用时机
extend() 必须在 check() 之前调用,且不能在验证器类内部直接写 $this->extend(...) —— 那样会导致每次实例化都重复注册,可能覆盖或冲突。
- 推荐写法:在控制器中 new 验证器后立刻 extend,或在验证器构造方法里统一 extend(但要加防重逻辑)
- 闭包内
$value不受 extend 方式影响,始终是当前字段值 - 若规则依赖外部服务(如查数据库判断用户名是否已存在),
$value是唯一可信入口,别绕路
最易忽略的一点:当字段值为 null、空字符串或 0 时,$value 就是它本身,不会被自动转成 false 或跳过——这意味着你的闭包必须显式处理这些边界值,否则 require 类规则可能被绕过。



















