在 Yii 中,要仅自动填充 created_at 而禁用 updated_at 的自动更新,需将 updatedAtAttribute 设为 false,并在 attributes 中仅配置 EVENT_BEFORE_INSERT 映射 created_at;同时排查其他行为、beforeSave 或数据库触发器导致的意外更新。

在 Yii 框架中,TimestampBehavior 默认会同时管理 created_at 和 updated_at 字段。若你只想让某个时间戳字段(比如 created_at)自动填充,而 updated_at 完全由业务逻辑手动控制、不被行为自动更新,就不能简单地“关闭一个字段”,而是要**精准配置行为的触发时机和字段映射**。
只启用 created_at,禁用 updated_at 的自动更新
关键在于:不把 updated_at 列入 attributes 映射中,并确保它不会出现在任何 EVENT_BEFORE_UPDATE 的处理列表里。
- 将
createdAtAttribute设为'created_at',保留创建时间自动写入 - 将
updatedAtAttribute设为false或null(Yii 会跳过该字段) -
attributes数组中,仅在EVENT_BEFORE_INSERT里包含'created_at',完全不提'updated_at'
示例配置:
public function behaviors()
{
return [
[
'class' => \yii\behaviors\TimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => false, // ← 明确禁用 updated_at 自动更新
'attributes' => [
\yii\db\ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
// EVENT_BEFORE_UPDATE 不配置任何字段 → updated_at 不会被触碰
],
'value' => new \yii\db\Expression('NOW()'),
],
];
}
如果 updated_at 字段仍被意外更新?检查这些地方
即使行为已禁用,updated_at 仍可能被改写,常见原因有:
- 模型中存在其他行为(如自定义 Behavior)或重写的
beforeSave()方法,手动设置了$this->updated_at = date('Y-m-d H:i:s') - 使用了
updateAll()批量更新,且 SQL 中显式写了updated_at = NOW() - 数据库层面设置了
ON UPDATE CURRENT_TIMESTAMP触发器或默认约束(MySQL 的 TIMESTAMP 类型默认行为)
彻底隔离 updated_at:推荐双保险策略
对关键字段要求绝对可控时,建议组合使用:
- 在
behaviors()中如上设置'updatedAtAttribute' => false - 在模型的
rules()中移除updated_at的安全赋值规则(即不列入safe或required),防止通过load()被批量赋值 - 在
beforeSave()中加一层防护:if (!$this->isNewRecord) { $this->updated_at = $this->getOldAttribute('updated_at'); }—— 强制保持原值


















