需用 Validate::make() 将数据库查出的二维规则数组(如 ['title'=>'require|max:50'])封装为验证器实例,再调用 check();避免与模型 $validate 冲突,推荐 new Validate()->rule($rules)->check($data) 脱离模型上下文。
验证规则从数据库读取后怎么塞进 ThinkPHP 的
方法里
ThinkPHP 的表单验证默认走静态规则(比如在模型里写
数组),但规则存数据库时,不能直接把数据库查出来的数组丢给
—— 它只认「规则定义」或「验证器类名」,不认纯数组(尤其 TP6.0+)。必须先转成验证器实例,再传进去。
查库拿到的规则是二维数组,例如:
,得用
包一层才能用
别在控制器里反复 new 验证器,每次请求都查库 + 构建,建议加一层缓存(比如用
)
TP6.1+ 支持传闭包作为规则,但闭包里查库容易引发循环依赖(比如验证器里又调模型,模型又触发验证),不推荐
和模型内置
属性冲突怎么办
如果模型已经定义了
属性,再用
会优先走模型里的静态规则,动态规则被忽略。这不是 bug,是 TP 的规则加载优先级设计:模型属性 > 外部传入规则(仅限
方法直接调用时)。
绕过模型验证逻辑:改用
,彻底脱离模型上下文
若仍想复用模型的场景钩子(如
、
),就把数据库规则合并进模型的
数组,而不是覆盖它——比如
注意
场景下,数据库规则也要按场景键组织,否则
可能漏掉动态字段
数据库字段怎么设计才方便映射成 TP 验证语法
别存原始 PHP 数组或 JSON 对象,要存可拼接的字符串规则。TP 的验证规则本质是「字段名 => 规则字符串」,所以数据库至少要有
、
、
三列,
值填
这种标准格式。
字段类型建议用
,别用
—— 复合规则(如带
列表)很容易超长
如果需支持多语言提示,
列存占位符格式,如
,TP 会自动替换
避免在数据库里存 PHP 代码或回调函数名(如
),除非你确认对应方法全局可用且无副作用
为什么验证通过了但
还返回空数组
常见于用了
却没处理批量错误模式。TP 默认单条失败就返回 false,
是字符串;开启
后,即使部分失败也返回 true,但错误信息全在
的数组里——这时候如果直接
,会输出
,看起来像“没错误”。
立即学习
“
PHP免费学习笔记(深入)
”;
检查是否调用了
,如果是,必须用
遍历
数据库规则里写了
但字段值是
或
,TP 默认会认为非空(
判的是
),结果验证通过但业务上其实该拒绝,这时得换
或自定义规则
规则里用了
(如确认密码),但数据库只存了
字段的规则,没配
字段的
,会导致验证静默失败
动态读规则这事本身不难,难在规则来源不可控时,
的翻译、
的隔离、
模式下的错误提取,这几处一旦漏掉,前端就收不到明确报错。
validate$rulevalidate()['title' => 'require|max:50', 'email' => 'email']Validate::make()Cache::get('form_rules')Validate::make()$validate$validatevalidate($data, $rules)validate()(new Validate())->rule($rules)->check($data)scenefilter$rule$this->rule = array_merge($this->rule, $dbRules)sceneonly(['title'])fieldrulemessagerulerequire|email|unique:user,emailruletextvarchar(255)inmessage':attribute 必须是邮箱格式':attributecallback:checkMobilegetError()Validate::make()->batch()->check($data)getError()batch()getError()echo $validate->getError()Arraybatch(true)foreach ($validate->getError() as $field => $msg)require0'0'requireempty()number|gt:0confirmpassword_confirmpasswordconfirm:password_confirmmessagescenebatch