CodeIgniter 不支持数据库 ON UPDATE CURRENT_TIMESTAMP 自动时间戳,需在模型 beforeUpdate 回调中手动设置 updated_at;迁移中建议用 DATETIME 类型并手写 ALTER 启用 ON UPDATE;避免控制器重复赋值,跨库需封装 now() 方法。

CodeIgniter 本身不提供数据库层面的 ON UPDATE CURRENT_TIMESTAMP 自动时间戳机制,也不像 Laravel 那样内置模型事件自动填充 updated_at。它的自动时间戳依赖于开发者在业务逻辑中主动设置——但可以通过规范写法和少量封装,做到接近“自动”的效果。
模型层统一赋值 updated_at
CodeIgniter 4 的模型(Model 类)支持 beforeUpdate 回调钩子,这是最推荐、最可控的方式:
- 在模型类中重写
beforeUpdate方法,每次执行$model->update()前自动注入当前时间 - 使用
date('Y-m-d H:i:s')或date('c')(ISO 8601 格式),确保与 MySQL 的DATETIME字段兼容 - 只对非空字段赋值,避免覆盖手动传入的
updated_at
示例:
app/Models/UserModel.phpprotected function beforeUpdate(array $data): array
{
if (isset($data['data']['id'])) {
$data['data']['updated_at'] = date('Y-m-d H:i:s');
}
return $data;
}
迁移文件中正确声明时间字段
虽然 CI 不管数据库定义,但为后续扩展和 ORM 兼容性,建议在迁移中显式声明时间字段行为:
- 用
datetime类型而非timestamp,避免时区转换和 2038 年限制 - 添加
DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP(MySQL 5.6.5+ 支持) - 注意:CI 迁移不解析这些属性,需手写 SQL 或用
$this->forge->modifyColumn()配合原生语句
迁移中推荐写法:
$this->forge->addColumn('users', [
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
'default' => null,
'constraint' => null,
'after' => 'created_at'
]
]);
// 然后单独执行 ALTER(因 forge 不支持 ON UPDATE)
$this->db->query("ALTER TABLE users MODIFY COLUMN updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP");
避免手动在控制器里写 NOW()
常见错误是在控制器中反复写 'updated_at' => date('Y-m-d H:i:s'),极易遗漏或不一致:
- 一旦忘记,
updated_at就不会更新,数据状态失真 - 若字段已定义
ON UPDATE CURRENT_TIMESTAMP,再手动赋值反而会禁用自动机制 - 建议把时间赋值逻辑收拢到模型或服务类,控制器只负责调用
$model->save($data)
注意不同数据库的兼容性
如果你的应用需要支持 PostgreSQL 或 SQLite:
- PostgreSQL 没有
ON UPDATE,必须靠触发器或模型层处理 - SQLite 不支持该语法,且
datetime('now')是唯一可靠方式,需在模型中判断方言动态生成 - CodeIgniter 的查询构造器不自动适配时间函数,跨库时建议封装一个
now()工具方法

















