thinkphp模型自动写入时间戳需同时满足开关开启、字段名配置、字段类型声明三者,缺一不可;否则$autowritetimestamp=true无效。

ThinkPHP 模型 $autoWriteTimestamp = true 为什么没生效
根本原因是自动写入时间戳不是“默认开启”,而是开关、字段名、字段类型三者缺一不可。只要漏掉一个,$autoWriteTimestamp = true 就等于没写。
常见失效场景:
- 数据库字段叫
updated_at,但模型里没配protected $updateTime = 'updated_at';,默认只认update_time - 字段类型是
INT,但没在模型中声明protected $type = ['update_time' => 'integer'];,ThinkPHP 会跳过自动写入 - 用了
Db::table('user')->update(...)或where()->update(),这类操作绕过模型层,beforeWrite钩子根本不触发 - 模型设置了
protected $readonly = ['update_time'],结果连更新都禁止了
update() 和 save() 对 updateTime 的行为差异
update() 是静态方法,内部其实调用了 isUpdate(true)->save(),所以它能触发自动更新;而裸用 save() 是否更新 update_time,取决于是否明确启用更新模式。
关键区别:
-
$user->save(['name' => 'foo']):如果没调isUpdate(true),且主键不存在(即新增),则只写create_time,不碰update_time -
$user->isUpdate(true)->save(['name' => 'foo'], ['id' => 1]):强制走更新流程,且仅当数据实际变更时才刷新update_time -
User::update(['name' => 'foo'], ['id' => 1]):等价于上一条,推荐用于简单更新 -
Db::name('user')->where('id', 1)->update(['name' => 'foo']):完全跳过模型,update_time不会自动更新
修改器 setUpdateTimeAttr 能否替代自动写入
可以,但不推荐用来做“自动更新”逻辑——因为修改器只在你显式给字段赋值时才执行,比如 $model->update_time = 'xxx',而 ThinkPHP 的自动写入是在检测到数据变更后、无须手动赋值就发生的。
如果你用修改器硬写:
-
public function setUpdateTimeAttr($value) { return $value ?: date('Y-m-d H:i:s'); },会导致每次save()都覆盖update_time,哪怕数据根本没变 - 它无法感知原始值(
$this->origin),所以做不到“仅当字段真变了才更新时间”的语义 - 真正适合用修改器的场景是格式转换(如小写化邮箱)、默认值兜底(
status为空时设为 1),不是生命周期标记
MySQL 严格模式下 update_time 写入失败怎么处理
错误现象通常是:Incorrect datetime value: '' for column 'update_time' 或直接报 SQL 错误。这是因为 ThinkPHP 自动写入默认用 date('Y-m-d H:i:s'),但在严格模式下,空字符串或非法时间会被拒绝。
稳妥做法:
- 数据库字段允许
NULL,并在模型中设protected $type = ['update_time' => 'datetime']; - 若必须非空,把字段默认值设为
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,再关闭模型的$updateTime,交由数据库托管(注意:这会让 PHP 层失去控制权) - 避免用
''或null直接传给 DATETIME 字段;改用'0000-00-00 00:00:00'(需 MySQL 兼容该模式)或真实时间戳 - 上线前务必确认
sql_mode包含STRICT_TRANS_TABLES,否则本地开发不报错,生产环境突然崩
最易被忽略的一点:自动写入只在模型方法内发生,且依赖 $this->origin 做变更比对——这个原始数据只在查询后调用 save() 才有;直接 new 模型然后 save(),$this->origin 为空,update_time 就不会更新。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











