yii模型中createdat和updatedat字段不会自动写入,必须配置timestampbehavior并确保rules()设为safe、value用new expression('now()')、数据库字段为datetime/timestamp。

Yii 模型中 createdAt 和 updatedAt 字段不自动写入?
默认情况下,Yii 的 ActiveRecord 不会自动填充时间戳字段——哪怕你命名成 created_at、updated_at 也没用。必须显式配置行为(TimestampBehavior)并指定对应属性。
常见错误是只加了行为但没在 rules() 里把字段设为 safe,或漏掉 value 的闭包写法导致始终写入 0 或 null。
- 确保数据库字段类型是
DATETIME或TIMESTAMP(不是INT) - 在模型的
behaviors()中返回TimestampBehavior,并用'value' => new Expression('NOW()')或function() { return date('Y-m-d H:i:s'); } - 如果字段名不是标准
created_at/updated_at,需在行为配置中显式指定'createdAtAttribute'和'updatedAtAttribute' -
TimestampBehavior默认只在insert和update场景生效;若需在批量更新(如updateAll)中也生效,得手动调用touch()或改用 SQL 表达式
TimestampBehavior 的 value 用 time() 还是 new Expression('NOW()')?
取决于时区和精度要求。PHP 的 time() 返回整数秒戳,填入 DATETIME 字段会变成 '1970-01-01 08:00:00' 这类错误值;而 date('Y-m-d H:i:s') 受 PHP 时区影响,可能和 MySQL 服务器时区不一致。
最稳妥的是让数据库自己生成:
'class' => TimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => new Expression('NOW()'),
这样既避免时区错位,又保证毫秒级一致性(MySQL 5.6.4+ 支持微秒)。如果必须用 PHP 侧生成,请统一设置 date_default_timezone_set('UTC') 并用 date('Y-m-d H:i:s')。
新增记录时 updatedAt 也被写了,但不希望它和 createdAt 相同?
这是 TimestampBehavior 的默认行为:只要启用了该行为,insert 时两个字段都会被赋值。如果你只想在创建时写 createdAt,更新时才改 updatedAt,就得拆开配置:
- 删掉全局
TimestampBehavior - 用两个独立行为:
'createdAt' => ['class' => TimestampBehavior::class, 'createdAtAttribute' => 'created_at', 'updatedAtAttribute' => false],'updatedAt' => ['class' => TimestampBehavior::class, 'createdAtAttribute' => false, 'updatedAtAttribute' => 'updated_at'], - 注意第二个行为要加
'skipUpdateOnClean' => true,否则空更新(没改任何字段)也会触发updatedAt变更
使用 save(false) 或批量操作时时间戳失效?
对,save(false) 跳过验证和事件,自然也跳过了 TimestampBehavior 的 beforeInsert/beforeUpdate 钩子。批量操作如 updateAll(['status' => 1], ['id' => $id]) 更是完全绕过模型层。
此时只能手动处理:
- 不用
save(false),改用save()并确保rules()允许时间字段为safe - 批量更新时,显式带上时间字段:
updateAll(['status' => 1, 'updated_at' => new Expression('NOW()')], ['id' => $id]) - 如果逻辑复杂,考虑封装一个
touchUpdated()方法,在关键路径里主动调用
别指望行为能覆盖所有边界场景——Yii 的时间戳填充本质是模型生命周期钩子,脱离这个上下文就得自己补。











