关闭ThinkPHP模型自动时间戳最稳方式是在模型类设protected $autoWriteTimestamp = false;若需差异更新则启用$autoWriteTimestamp = true并确保字段名正确,同时明确定义$type避免时间值被覆盖。

关闭 ThinkPHP 模型自动写入 create_time 和 update_time
默认开启时,ThinkPHP 会在 insert() 或 save() 时偷偷塞入时间值,不关掉就很难做手动赋值或跳过更新。关键不是“能不能关”,而是关在哪一层最稳——模型类里关,比全局配置更精准,也避免影响其他模型。
- 在模型类中显式设
protected $autoWriteTimestamp = false;,这是最直接、优先级最高的开关 - 如果只希望禁用某次操作(比如导入历史数据),可在调用时传参:
->save($data, ['auto_timestamp' => false]) - 注意:若已定义
protected $createTime或$updateTime,即使关了$autoWriteTimestamp,字段名仍会被识别;如不需要自动处理,建议一并删掉这两个属性
让 update_time 只在真正修改数据时更新
默认行为是每次 save() 都刷 update_time,哪怕字段值根本没变。这会导致无意义的时间戳污染,查日志或做乐观锁时特别容易误判。
- 启用差异更新:在模型中设
protected $updateTime = 'update_time';(确保字段名正确),再加protected $autoWriteTimestamp = true;,此时 ThinkPHP 会对比原始数据和新数据,仅当有字段变更才写update_time - 但注意:这个“差异判断”只针对当前
save()调用中传入的字段,不是全量比对;若用allowField()限制了字段,未传的字段变动不会触发更新 - 如果用了软删除(
delete_time),它不受此机制影响,删除时仍会强制写入
create_time 被覆盖成当前时间?检查是否漏写了 default 或 type
有时你明明传了 'create_time' => '2020-01-01',保存后却变成服务器当前时间。这不是 bug,是 ThinkPHP 的字段类型推断在作祟。
- 数据库字段如果是
DATETIME或TIMESTAMP,且模型里没声明type,ThinkPHP 可能按字符串处理,然后被自动转成时间戳再格式化,最终“覆盖”你传的值 - 解决方法:在模型中明确定义
protected $type = ['create_time' => 'datetime'];(或'timestamp'),告诉框架“别动我传的值,原样存” - 如果字段允许为 NULL,且你传了
null,记得确认数据库约束和模型$dateFormat是否一致,否则可能被转成'0000-00-00 00:00:00'
全局关闭自动时间戳的副作用
在 config/database.php 里设 'auto_timestamp' => false 看似一劳永逸,但实际会同时关掉所有模型的自动时间处理,包括你可能依赖它的其他业务模型。
立即学习“PHP免费学习笔记(深入)”;
- 更麻烦的是:部分中间件、行为(behavior)或扩展包会基于该配置做逻辑分支,关掉后可能引发隐性异常,比如日志记录时间为空、审计字段缺失
- 如果你只是想统一管理时间字段逻辑,建议用基类模型封装:
BaseModel extends Model,在里面统一控制$autoWriteTimestamp和$type,各业务模型继承即可 - 别忘了:命令行环境(如
php think xxx)下,模型行为和 HTTP 请求时完全一致,该踩的坑一个都不会少



















