Yii模型调用update()不更新updated_at,根本原因是TimestampBehavior未触发或配置错误;需确保行为已注册、EVENT_BEFORE_UPDATE明确映射updated_at、使用save()而非save(false)或updateAll()、字段类型匹配且模型属性确实变更。

Yii 模型调用 update() 时不更新 updated_at,根本原因是 TimestampBehavior 没有被触发,或者行为配置与当前操作不匹配。这不是 update() 方法本身的问题,而是时间戳自动更新依赖行为(Behavior)的规则是否生效。
TimestampBehavior 必须正确配置才能响应 update
updated_at 字段由 TimestampBehavior 自动维护,但它只在满足以下条件时才写入新值:
- 行为已注册在模型的
behaviors()中 -
attributes配置明确声明了EVENT_BEFORE_UPDATE对应updated_at - 当前执行的是
ActiveRecord::update()(非save(false)、非直接 SQL、非批量更新) - 模型实例确实发生了属性变更(
getDirtyAttributes()不为空),否则 Yii 可能跳过实际 UPDATE 语句
典型正确配置示例:
public function behaviors()
{
return [
[
'class' => \yii\behaviors\TimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'attributes' => [
\yii\db\ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
\yii\db\ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], // ← 关键:必须包含此项
],
'value' => new \yii\db\Expression('NOW()'),
],
];
}常见导致 updated_at 不更新的原因和对策
-
调用了
save(false)save(false)会跳过验证和行为(包括 TimestampBehavior)。
✅ 改用save()或显式触发:$model->touch('updated_at'); // 简单有效,自动赋 NOW() 并 save -
手动修改后未调用
update(),而是用了updateAll()updateAll()是静态方法,绕过模型生命周期,不触发任何行为或事件。
✅ 改为实例方式更新:$model->status = 'done'; $model->save(); // 触发 behavior
或保留
updateAll()时手动设置时间:Model::updateAll(['updated_at' => new \yii\db\Expression('NOW()')], ['id' => $id]); -
数据库字段类型不兼容
NOW()表达式
若updated_at是INT类型(存时间戳整数),'value' => new Expression('NOW()')会写入0或报错。
✅ 改为:'value' => function() { return time(); } // 适配 INT或统一使用
DATETIME/TIMESTAMP类型(推荐)。 -
模型未真正“变脏”(dirty)
Yii 默认只对发生变更的属性生成SET子句。如果所有属性值和数据库一致,update()实际不发 SQL,自然也不会更新updated_at。
✅ 强制标记为脏:$model->updated_at = null; // 先清空,让 behavior 重写 $model->save();
或直接
touch()更稳妥。 行为被其他逻辑覆盖或未加载
检查behaviors()是否被父类/traits 覆盖;确认该模型类没禁用行为(如return [];);调试时可临时加日志到 behavior 的evaluateValue()看是否执行。
不复杂但容易忽略


















