$model->errors() 总是空数组,因为验证未显式触发;CI4 中 set_rules() 已废弃,需直接传规则数组给 validate();验证与保存必须使用同一数据源;多文件上传需通过 getError() 判断是否真实上传。

为什么 $model->errors() 总是空数组?
因为模型里的 $validationRules 只是配置容器,不自动触发验证。你没在控制器里调用 validate(),系统根本没跑校验逻辑,$model->errors() 当然永远返回空数组。
必须显式调用验证方法,且传入待验证的数据(通常是 $this->request->getPost()):
- 用辅助函数:
if (!$this->validate($rules)) { ... } - 或用 Validation 服务:
$validator = \Config\Services::validation(); $validator->run($data, $rules); - 验证失败后,用
$this->validator->getErrors()或$validator->getErrors()拿错误,不是$model->errors()
set_rules() 在 CI4 还管用吗?
不管用。set_rules() 是 CI3 的写法,CI4 已移除该方法。直接用数组规则传给 validate() 即可,不需要先“设置”再“运行”。
常见错误是照搬 CI3 写法:
- ❌ 错误:
$this->form_validation->set_rules(...)(类不存在) - ✅ 正确:
$rules = ['email' => 'required|valid_email']; $this->validate($rules); - 自定义消息也直接塞进规则数组:
'email' => ['rules' => 'required', 'errors' => ['required' => '邮箱必填']]
验证通过了但数据没进数据库,是不是漏了什么?
很可能是验证和保存用了两套数据源:验证时用 $this->request->getPost(),保存时却用 $this->request->getVar() 或没过滤,导致字段名/值不一致。
确保前后一致:
- 验证和插入都基于同一份数据,推荐先取出来再复用:
$data = $this->request->getPost(['username', 'email']); - 验证通过后再调
$model->insert($data),别在insert()里重新取一遍 - 如果模型启用了自动验证(
$skipValidation = false),记得insert()会再次触发验证 —— 这时要确保模型的$validationRules和控制器里的一致,否则可能二次失败
多文件上传验证老是误判有文件?
$this->request->getFileMultiple('files') 即使用户没选任何文件,也会返回一个含空 UploadedFile 对象的数组,if ($files) 永远为真。
真正判断有没有上传,得看每个对象的 error 属性是否等于 UPLOAD_ERR_NO_FILE(值为 4):
- 遍历数组:
foreach ($files as $file) { if ($file->getError() !== UPLOAD_ERR_NO_FILE) { ... } } - 只对
getError() === 0的文件做移动、验证等操作 - 验证规则里别写
required,它对文件字段无效;改用逻辑判断 + 自定义错误
CI4 验证不是“配完就跑”,它依赖明确的执行时机和数据上下文。最容易被忽略的是:验证结果不存模型里,而存在 Validation 实例中;以及多文件场景下,getError() 才是唯一可信的判断依据。


















