Yii框架需显式配置TimestampBehavior才能自动处理created_at/updated_at字段,常见失效原因包括行为未注册、字段名不匹配、数据库类型与时间生成方式冲突,须正确配置behaviors()方法、字段映射及时区策略。

Yii框架默认不会自动处理 created_at 和 updated_at 字段,必须显式配置 TimestampBehavior 才能生效。不生效的常见原因不是代码写错,而是行为未注册、字段名不匹配、或数据库类型与时间生成方式冲突。
确保 behaviors() 方法正确返回 TimestampBehavior
在模型类中重写 behaviors(),返回数组形式的行为配置,不能遗漏 class 路径和事件绑定:
- 必须使用完整命名空间:
\yii\behaviors\TimestampBehavior::class -
attributes需明确指定触发时机:EVENT_BEFORE_INSERT和EVENT_BEFORE_UPDATE - 若字段名为
create_time或mtime,需同步修改createdAtAttribute和updatedAtAttribute - 推荐用
new \yii\db\Expression('NOW()')而非time(),避免时区偏差(尤其 MySQL 的DATETIME类型)
检查数据库字段类型与 PHP 时间生成逻辑是否匹配
不同字段类型对应不同的时间填充策略:
-
DATETIME字段:用NOW()表达式最稳妥,MySQL 自动按当前会话时区解析 -
TIMESTAMP字段:MySQL 默认按 UTC 存储并转本地显示,但 Yii 不感知该机制;建议统一改用DATETIME+ PHP 层控制时区 - 整型时间戳(int)字段:改用
'value' => time(),但需确保数据库字段允许 NULL 或有默认值,否则插入失败 - 字段不允许 NULL 且无默认值时,
EVENT_BEFORE_INSERT必须覆盖全部目标字段,否则报 SQL 错误
排除干扰项:手动赋值、beforeSave 重写、迁移脚本残留
以下情况会导致 TimestampBehavior 被绕过:
- 在
beforeSave()中直接给$this->created_at = ...赋值,会覆盖 behavior 的逻辑 - 数据库迁移里设置了
DEFAULT CURRENT_TIMESTAMP,但 PHP 层又试图写入 NULL,触发 MySQL 强制默认值,而 model 实际未更新该属性 - 批量插入(
insertAll)不触发 AR 生命周期,behavior 完全不执行——此时需在 SQL 层处理或改用循环 save() - 调用
updateAll()时也不会触发 behavior,必须显式传入时间字段值
快速验证是否生效
不依赖日志或前端展示,直接用最小化测试确认:
- 新建模型实例:
$model = new YourModel(); $model->name = 'test'; $model->save(); - 查数据库,看
created_at是否有值、是否为当前时间(注意时区) - 再执行
$model->name = 'updated'; $model->save();,检查updated_at是否变化且晚于created_at - 若仍为空,临时在 behavior 的
value中加日志:function () { \Yii::debug('timestamp triggered'); return new \yii\db\Expression('NOW()'); }


















