thinkphp 6.x 模型 validate 属性不生效,因自动验证已移除,须显式调用 validate 实例 check() 或模型 validatescene();场景分离、验证前置、字段大小写一致是关键。

模型定义里加 validate 规则不生效?
ThinkPHP 的模型字段必填校验,不能只靠模型类里的 validate 属性静态声明——它默认只在调用 validate(true) 或开启自动验证时才触发,而新版(6.x)中自动验证已被移除,必须显式调用。
常见错误是写了 protected $validate = ['name' => 'require'] 就以为插入时会拦住空值,结果数据直接进库了。
- ThinkPHP 6.x 必须配合
Validate类或使用模型的validateScene()显式校验 - 若用
save(),需手动加->validate(true)(仅限 5.x);6.x 推荐改用Validate实例 +check() - 字段名大小写要和数据库/模型属性严格一致,
user_name和username被当成两个字段
创建和更新用同一套验证规则?小心覆盖问题
新增(create)和修改(update)场景下,有些字段该必填、有些不该,比如 id 更新时必传但创建时不填,password 创建时必填但更新时可为空。
硬写死一套 rule 容易出错,ThinkPHP 提供了场景(scene)机制来隔离逻辑。
- 定义验证规则时用
scene('create')和scene('update')分开配置 -
create场景下给password加require,update场景下换成confirm或去掉 - 调用时必须显式指定:
$model->validate('create')->save($data),否则默认走default场景(可能没定义) - 注意:6.x 中
scene是Validate实例的方法,不是模型属性
用 allowField 过滤字段后,验证还生效吗?
很多人用 allowField(['name', 'email']) 防止恶意传参,但发现即使字段被过滤掉,验证器仍报“mobile 不能为空”——因为验证发生在数据过滤之前。
验证器看到的是原始输入数据,allowField 是后续入库前的白名单控制,两者不在同一环节。
- 验证阶段的数据源是传给
save()或create()的完整数组,和allowField无关 - 如果只想对部分字段验证,得在验证规则里用
only指定字段,或拆成多个Validate实例 - 更稳妥的做法:先验证,再
allowField,最后保存;顺序错了就等于白验
数据库字段为 NOT NULL,但 PHP 层没校验,会怎样?
靠数据库约束兜底看似省事,但实际会抛出 PDO 异常,如 SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value,前端看到的是 500 错误,没法友好提示用户。
这不是校验逻辑的问题,而是错误处理层级错位:数据库是最后防线,应用层才是第一道关卡。
- 数据库
NOT NULL只防漏网之鱼,不能替代业务校验 - ThinkPHP 验证失败会返回
false或抛ValidateException,可被捕获并转成 JSON 提示 - 尤其注意时间字段(
created_at):如果模型自动写入,验证器别对它设require,否则必失败
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










