Yii框架推荐使用TimestampBehavior自动处理created_at和updated_at字段,通过行为监听事件赋值,需正确配置字段名、事件映射及value类型(INT用time(),DATETIME用NOW()),并注意字段存在性与类型匹配。

Yii 框架中 TimestampBehavior 是处理创建时间(created_at)和更新时间(updated_at)最常用、最推荐的方式。它不是手动在 beforeSave 里写逻辑,而是通过行为(Behavior)自动注入时间值,干净、复用性强、不易遗漏。
基础配置:字段名与事件绑定
默认情况下,该行为会监听 EVENT_BEFORE_INSERT 和 EVENT_BEFORE_UPDATE 事件,并自动为 created_at 和 updated_at 赋值。但你要确保模型类中明确声明字段映射:
-
createdAtAttribute指定哪个字段存创建时间(如'created_at') -
updatedAtAttribute指定哪个字段存更新时间(如'updated_at') -
attributes数组精确控制每个事件触发时更新哪些字段,例如:
<?php
public function behaviors()
{
return [
[
'class' => yiiehaviorsTimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'attributes' => [
yiidbActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
yiidbActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
],
];
}
时间值来源:UNIX 时间戳 vs DATETIME 字符串
字段类型决定你该用哪种 value 方式:
- 如果数据库字段是
INT(存 UNIX 时间戳),直接用'value' => time()或省略value(默认就是time()) - 如果字段是
DATETIME或TIMESTAMP(如 MySQL),推荐用数据库函数避免时区偏差:'value' => new yiidbExpression('NOW()') - 不建议用 PHP 的
date('Y-m-d H:i:s')函数——它依赖 PHP 时区设置,且可能和数据库时区不一致
字段存在性与健壮性处理
原生 TimestampBehavior 对不存在的字段会报错。若想让行为更“宽容”,比如在基类统一配置、又不想每个子模型都检查字段是否存在,可考虑:
- 在
behaviors()中先用$this->hasAttribute()判断字段是否存在再加入attributes数组 - 或使用社区改进版
TimestampBehavior(继承自AttributeBehavior),自动过滤掉模型中不存在的字段名 - 注意:不要把
created_at和updated_at写进rules(),它们由行为自动赋值,无需验证
常见踩坑点
这些细节容易导致时间没更新或报错:
- 数据库字段名拼错(如
create_at少了个d),行为会静默失败或抛异常 - 字段类型与
value类型不匹配(比如用time()往DATETIME字段写,结果存成1970-01-01 08:00:01) - 在事务中多次 save 同一模型,
updated_at只会在真正执行 UPDATE SQL 时更新,不是每次调用save()都触发 - 手动给
updated_at赋值(如$model->updated_at = ...)会绕过行为,导致行为不再覆盖该字段


















