thinkphp 6 中 _autowritetimestamp 已废弃,应改用 protected $createtime = 'create_time'; protected $updatetime = 'update_time'; 并设置 protected $autowritetimestamp = true;,同时确保字段存在且类型匹配。

ThinkPHP 模型里 _autoWriteTimestamp 不生效?先看版本和写法
ThinkPHP 6 和 ThinkPHP 5 的时间戳自动写入机制完全不同,_autoWriteTimestamp 是 TP5 的写法,在 TP6 中已废弃。如果你用的是 TP6 却照搬 TP5 的模型配置,它根本不会触发——连警告都不会抛。
实操建议:
- TP5.1:在模型类中定义
protected $autoWriteTimestamp = true;(注意是小驼峰,不是下划线);_autoWriteTimestamp是旧版 TP3/TP4 的写法,TP5 已不认 - TP6.x:改用
protected $createTime = 'create_time'; protected $updateTime = 'update_time';,并确保开启自动写入:protected $autoWriteTimestamp = true;(TP6 中这个属性仅控制「是否启用」,字段名由上面两个属性决定) - 别漏掉数据库字段:
create_time和update_time必须存在,且类型推荐DATETIME或TIMESTAMP;若用INT存时间戳,需额外设protected $type = ['create_time' => 'integer'];
为什么 save() 写入了但时间戳没变?检查操作方式
自动时间戳只在特定方法中触发:TP5/6 都只对 save()、create()(TP5)、data()->save()(TP6)等「主动写入」行为生效;直接执行 Db::table()->insert() 或原生 SQL 不会触发。
常见错误现象:
- 用了
$model->allowField(true)->save($data),但$data里手动传了'create_time' => time()—— 这会覆盖自动写入逻辑 - 调用
$model->isUpdate(true)->save()时,TP6 默认只更新updateTime,但如果你没设$model->id或主键值为空,它会当成新增,却因isUpdate(true)跳过createTime写入 - TP5 中
create()方法默认不启用时间戳,必须显式传参:$model->create($data, true)第二个参数为true才触发自动赋值
时间戳字段名不叫 create_time 怎么办?改配置别硬编码
很多项目用 created_at / updated_at,或全大写 CREATE_TIME。硬改数据库字段名成本高,应通过模型配置适配。
实操建议:
- TP6:直接改
protected $createTime = 'created_at'; protected $updateTime = 'updated_at'; - TP5:用
protected $createTime = 'created_at'; protected $updateTime = 'updated_at'; protected $autoWriteTimestamp = true; - 注意大小写敏感:MySQL 在 Linux 下表字段名区分大小写,
Created_At和created_at是两个字段,配置必须完全一致 - 如果字段是
INT类型存秒级时间戳,TP6 要加类型转换:protected $type = ['created_at' => 'integer', 'updated_at' => 'integer'];,否则会尝试写入字符串格式的日期
批量插入(saveAll)为何只有第一条有时间戳?
saveAll() 在 TP5 和 TP6 中行为不一致:TP5 的 saveAll() 本质是循环调用 save(),时间戳正常;TP6 的 saveAll() 默认走批量 INSERT 语句,不逐条实例化模型,因此自动时间戳逻辑被跳过。
解决路径很直接:
- TP6 中想保持自动时间戳,改用
foreach+save():避免用saveAll(),尤其当数据量不大( - 若必须批量插入且要时间戳,手动补字段:
$dataList = array_map(fn($item) => array_merge($item, ['created_at' => date('Y-m-d H:i:s')]), $dataList);,再调用Db::name('table')->insertAll($dataList) - TP5 中
saveAll()支持传参控制:$model->saveAll($list, ['replace' => false]),但时间戳仍依赖单条模型实例化,大批量时注意内存占用
最易被忽略的一点:TP6 的模型时间戳默认使用 date('Y-m-d H:i:s') 格式,如果你数据库字段是 TIMESTAMP 且设置了 DEFAULT CURRENT_TIMESTAMP,PHP 写入的值可能和 MySQL 自带的默认值冲突,导致部分场景下 updateTime 没更新——这时候得关掉数据库层面的自动更新,统一由 PHP 控制。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











