CI4模型update()方法仅支持按主键更新单条记录,需配置$primaryKey、$table、$allowedFields三属性,调用时必须传入主键值与数据数组,否则可能静默失败或误更新全表。

CI4 模型的 update() 方法不是“通用更新接口”,它本质是按主键更新单条记录。想用模型实现“统一调用方式”,关键不是绕过规则,而是把规则用对、用稳。
必须配齐模型基础属性
模型类里这三项缺一不可,否则 update() 会静默失败或误更新全表:
-
$primaryKey:明确指定主键字段名,如
protected $primaryKey = 'id_user';(必须和数据库字段完全一致) -
$table:声明操作的表名,如
protected $table = 'users'; -
$allowedFields:白名单数组,只列允许被 update 写入的字段,如
protected $allowedFields = ['nama_user', 'email', 'status'];。不在这个数组里的字段,无论传什么,update() 都直接返回 false
调用 update() 的标准写法
控制器中必须传两个参数:主键值 + 数据数组。不能只传数据:
- ✅ 正确:
$model->update($id, ['status' => 'approved']); - ❌ 错误:
$model->update(['status' => 'approved']);(没 ID,可能更新整张表) - ❌ 错误:
$model->update(null, [...]);或$model->update('', [...]);(ID 为空,update() 返回 false)
ID 通常来自表单隐藏域或 URL 参数,取值后建议先判断有效性:$id = $this->request->getPost('id'); if (empty($id)) { // 报错或跳转 }
想按其他条件更新?别硬套 update()
如果业务需要“更新所有 status=pending 的记录”,就不要用模型的 update() 方法。改用 Query Builder 显式构造 where 条件:
$model->builder()->where('status', 'pending')->update(['updated_at' => date('Y-m-d H:i:s')]);- 这种写法不走 $allowedFields 白名单,也不依赖 $primaryKey,但你要自己确保字段安全(比如过滤输入、类型转换)
- 它返回影响行数,可据此判断是否成功,例如:
if ($model->builder()->where(...)->update(...) === 0) { // 无匹配记录 }
单选按钮等表单字段要额外校验
单选按钮传过来的值容易非法(比如篡改 HTML 提交 'admin' 但用户没权限)。更新前建议做两件事:
- 限定合法选项范围,例如:
$validStatus = ['draft', 'published', 'archived']; if (!in_array($status, $validStatus)) { throw new \RuntimeException('Invalid status'); } - 强制类型转换,避免字符串 '1' 和整数 1 混淆,例如:
'status' => (string)$status或'is_active' => (bool)$isActive

















