根本原因是TimestampBehavior不自动传播到关联模型,需在各关联模型中独立配置行为、确保字段名准确、手动触发save(false)更新时间戳,或用改进版行为及数据库默认值兜底。

Yii框架中关联模型的时间戳(如 created_at、updated_at)不更新,根本原因在于:ActiveRecord 的 TimestampBehavior 默认只作用于当前模型的保存生命周期,**不会自动传播到关联模型**。也就是说,主模型调用 save() 时,关联模型即使被一起保存(如通过 link() 或嵌套验证),其时间戳也不会被行为自动填充。
确认时间戳行为是否已正确配置在关联模型类中
这是最常被忽略的前提。每个需要自动更新时间戳的模型(包括关联模型),都必须独立声明 TimestampBehavior:
- 检查关联模型(例如
OrderItem)的behaviors()方法,确保已返回完整配置,不能依赖主模型(如Order)的行为“传染”过去; - 字段名(
createdAtAttribute、updatedAtAttribute)必须与数据库实际字段严格一致,拼错或大小写不符都会静默失效; - 推荐使用
new Expression('NOW()')而非闭包函数,避免时区或执行时机偏差。
关联保存时手动触发时间戳更新
当通过 $order->link('items', $item) 或批量赋值(如 $order->items = [$item1, $item2])并调用 $order->save() 时,关联模型不会走自己的 beforeSave 流程。此时需显式干预:
- 在主模型的
afterSave()中遍历关联对象,逐个调用save(false)(跳过验证,仅触发行为); - 若使用
link(),可在链接后立即对被链接模型调用save(false); - 避免在
beforeSave()中操作关联模型,易引发循环保存或事务异常。
使用改进版 TimestampBehavior 提升健壮性
原生 TimestampBehavior 对不存在字段敏感,且无法跨模型生效。可采用社区优化版本(如 common/behaviors/TimestampBehavior.php):
- 支持动态过滤字段:即使配置了
logined_at这样不存在的字段,也会自动跳过,不报错; - 允许统一基类配置:在
BaseModel中定义通用行为,子类无需重复声明; - 兼容关联场景:配合
afterSave()手动调用,能更安全地覆盖多层嵌套模型的时间戳需求。
数据库层面兜底(适用于关键业务)
对强一致性要求高的场景(如订单项创建时间必须精准),可在数据库设置默认值和自动更新:
- MySQL 中将字段设为
TIMESTAMP DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP; - 注意:此方式 Yii 模型读取不到实时值,需在查询后主动
refresh(); - 不建议同时开启数据库自动更新 + PHP 层行为,易造成冲突或重复更新。


















