yii 2.0.39 的 timestampbehavior 支持多字段时间戳配置,需显式通过 attributes 映射事件与字段,适配字段类型选择 time() 或 now(),并校验字段存在性以避免异常。

Yii 2.0.39 中的 TimestampBehavior 完全支持多字段时间戳配置,关键在于明确指定每个字段的触发时机和值来源,避免字段名错误或事件绑定错位。
基础写法:显式声明多个字段
如果你的表里有 created_at、updated_at、published_at、deleted_at 等多个时间字段,不能只靠默认行为,必须在 behaviors() 中逐个定义:
-
createdAtAttribute和updatedAtAttribute只控制两个默认字段,不扩展到其他字段 - 其余字段需通过
attributes数组手动映射事件与属性 - 例如让
published_at仅在EVENT_BEFORE_INSERT时设为当前时间,deleted_at在EVENT_BEFORE_UPDATE时才填充(软删除场景):
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['published_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['deleted_at'],
],
'value' => function () {
return date('Y-m-d H:i:s'); // 或 new Expression('NOW()')
},
],
];
}
字段类型适配:int 还是 datetime?
字段类型决定 value 的写法,且影响数据库兼容性:
- 若字段是
INT(11)存 UNIX 时间戳,value应返回time() - 若字段是
DATETIME或TIMESTAMP,推荐用new Expression('NOW()'),由数据库生成更可靠(避开 PHP 时区/服务器时间不准问题) - 字段为
NULL允许时,value函数可加判断逻辑,如只在特定条件下赋值
安全兜底:防止不存在字段报错
原生 TimestampBehavior 遇到模型中不存在的字段名会直接抛异常。2.0.39 版本虽未内置容错,但可通过轻量封装规避:
- 在
attributes中列出的字段,先用in_array($attr, $this->owner->attributes())校验是否存在 - 更稳妥的做法是继承并重写
evaluateAttributes(),跳过无效字段(参考社区改进版 TimestampBehavior) - 尤其在多模型复用同一 behavior 配置时,该检查能避免上线后因某张表缺字段而崩溃
关联与批量操作注意事项
时间戳行为在以下场景不会自动触发,需额外处理:
-
ActiveRecord::updateAll()或deleteAll()等静态方法——绕过模型生命周期,行为不生效 - 关联模型保存(如
$model->link())——主模型行为运行,但关联模型需单独配置 - 事务中多个模型同时 save —— 各自 behavior 独立执行,无顺序依赖,但要注意数据库 NOW() 的毫秒级一致性











