ThinkPHP 8.0启用模型自动时间戳需三步:设$autoWriteTimestamp = true、准确声明$createTime和$updateTime字段名、确保数据库存在对应DATETIME/TIMESTAMP字段;否则静默失效。

ThinkPHP 8.0 中启用模型自动时间戳,关键在于三件事:显式开启功能、准确声明字段名、确保字段存在且类型匹配。它不默认开启,也不自动推导字段,错一处就静默失效。
必须设置的模型属性
在模型类中(如 app/model/User.php)明确写入以下三项:
-
开启自动写入:
protected $autoWriteTimestamp = true;(不能省略,TP8 默认为false) -
指定创建时间字段:
protected $createTime = 'create_time';(若数据库用created_at,就写'created_at') -
指定更新时间字段:
protected $updateTime = 'update_time';(同样需与数据库列名完全一致,含大小写和下划线)
数据库字段要提前准备好
对应字段必须真实存在于数据表中,推荐使用 DATETIME 或 TIMESTAMP 类型:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 如果用
INT存时间戳,需额外声明类型转换:protected $type = ['create_time' => 'integer', 'update_time' => 'integer']; - 字段名必须和模型中
$createTime、$updateTime的字符串值**一字不差**,比如写成'CreateTime'而数据库是create_time,就不会生效
注意触发时机和常见干扰
自动时间戳只在模型方法中触发,例如 save()、data()->save()、saveAll()(开启 batch 参数时也有效),但不会在以下情况工作:
立即学习“PHP免费学习笔记(深入)”;
-
Db::name('user')->insert()等原生查询或门面操作 -
allowField(true)或显式传了field数组,却没包含时间戳字段名——它们会被过滤掉 - 手动在数据数组中传入
'create_time' => ...,会直接覆盖自动写入逻辑 - 调用
isUpdate(true)->save()但主键为空,系统误判为新增,却因isUpdate跳过createTime写入
进阶控制(可选)
如需更精细管理,可用 $autoWrite 替代基础配置:
protected $autoWrite = ['create_time' => ['datetime', 'insert'], 'update_time' => ['datetime', 'update']];- 支持闭包生成值,例如 UUID:
'uuid' => [function () { return \think\helper\Str::uuid(); }, 'insert'] - 动态值(如当前登录用户 ID)必须用
before_write事件,在回调中手动赋值


















