必须写在模型里。thinkphp的validate和auto机制仅在模型层生效,控制器调用create()或save()时触发;规则须赋值给模型的$validate(tp3)或$rule(tp5+),tp5.1+推荐用validate类并显式启用。

验证规则写在模型里还是控制器里?
必须写在模型里。ThinkPHP 的 validate 和 auto 机制只在模型层(Model 或 BaseModel 子类)中生效,控制器调用 create() 或 save() 时才触发。写在控制器里等于没写。
常见错误:在控制器里手动调用 check() 却没绑定规则,或把规则数组直接丢进 add() 参数——这些都不走框架验证流程。
- 规则数组必须赋值给模型的
$validate属性(TP3)或通过protected $rule = []定义(TP5+) - TP5.1+ 推荐用验证器类(
Validate类),但模型内仍需通过validate(true)显式启用 - 字段名必须与数据表字段完全一致,大小写敏感;若用下划线命名法,别误写成驼峰
“required”不生效?检查这三处
required 规则失效,90% 是因为字段值为 ''、null 或未提交(HTML 表单中 name 缺失),但验证器默认对空字符串放行——除非显式配置 ['require' => true] 或使用 ['empty' => false]。
- TP5+ 验证器中,
'require' => true只校验是否传参,不校验值是否为空;真正拦截空字符串要用'regex' => '/\S+/'或自定义函数 - HTML 表单中 checkbox、select multiple 未选中时不会提交字段,后端收不到该 key,
required自然跳过——应配合default或前端 JS 补默认值 - 用
input('post.')手动取参再传入验证器时,注意过滤了空格或 trim 过度导致原值被转成空字符串
自动完成(auto)和自动验证(validate)的执行顺序
TP3 中,create() 先执行 auto(含 insert / update 类型),再执行 validate;TP5+ 改为先验证再自动完成(allowField 后、save() 前)。这个顺序直接影响逻辑安全。
- 比如密码加密:TP3 中若在
auto里写['password', 'md5', 3, 'function'],验证的是明文;TP5+ 必须把加密逻辑移到验证器的scene或filter中,否则验证完就直接入库了 -
auto中的ignore类型(忽略字段)在 TP5+ 已废弃,改用except或白名单allowField - 时间戳字段如
create_time若同时设auto和数据库默认值,容易冲突——建议只留一处,推荐由模型控制
验证失败时如何拿到具体错误信息?
别只依赖 $model->getError() 返回的字符串。它在 TP5+ 中默认只返回第一条错误,且格式不统一;实际调试或 API 返回需要结构化数据。
- TP5.1+ 使用独立验证器时,调用
$validate->batch()->check($data),再用$validate->getError()可得完整数组 - 模型验证失败后,
$model->data仍是原始输入,$model->getChangedData()为空——说明自动完成根本没跑,要回头查执行顺序 - AJAX 提交时,后端最好统一返回
['code'=>0, 'msg'=>'', 'data'=>[]]结构,错误信息塞进msg或新增errors字段,避免前端反复解析字符串
验证规则嵌套层级、场景切换(scene)、以及与事务的配合,是线上最容易出问题的地方。别图省事把所有规则堆在一个数组里,也别在事务外做自动完成再手动 save——这两处一错,数据状态就不可逆。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











