created_at 是只读审计字段,代表数据首次写入时间,不可手动修改;应通过新增业务字段(如effective_at)或直接SQL更新(仅限修正录入错误)来满足实际需求。

在 Yii 2.0.47 中,created_at 是只读字段,代表记录创建时刻,**不应也不允许在创建后手动修改**。如果你发现需要“修改 created_at”,通常说明业务场景理解有偏差——比如把“首次有效时间”误当成了“创建时间”,或实际想更新的是 updated_at 或其他业务时间字段。
为什么不能改 created_at?
这是设计原则问题:
• created_at 的语义是“数据行第一次写入数据库的时间”,具有审计和不可篡改性;
• Yii 的 TimestampBehavior 默认在 beforeInsert 触发一次赋值,之后不再介入该字段;
• 即使你绕过行为、在控制器里强行赋值(如 $model->created_at = '2025-01-01'),只要该字段在模型规则中未被设为 safe 或未显式允许批量赋值,load() 就会忽略它;
• 强行更新还可能破坏数据一致性(例如日志、同步、统计逻辑依赖原始创建时间)。
真要调整时间,该怎么做?
根据真实需求选择对应方式:
-
想修正录入错误的初始时间:直接执行 SQL 更新(需谨慎并留痕)
UPDATE your_table SET created_at = '2025-01-01 10:00:00' WHERE id = 123;
注意:确保数据库时区与应用一致,避免因TIMESTAMP类型导致隐式转换偏差。 -
想记录另一个业务时间点(如“生效时间”“上线时间”):新增字段(如
effective_at),并在模型中加规则和行为支持['effective_at', 'safe'](rules 中)
并可选配独立的TimestampBehavior或普通赋值逻辑。 -
误操作导致 created_at 为空或异常:检查是否漏了行为配置,或数据库字段默认值冲突
• 确保模型中已声明TimestampBehavior,且createdAtAttribute指向created_at;
• 数据库字段不要设DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP—— 这会与 Yii 行为争抢控制权;
• 若字段类型是DATETIME,建议用Expression('NOW()');若是INT,用function () { return time(); }。
如果坚持要在代码中覆盖(不推荐)
仅限极特殊迁移或修复场景,且必须跳过安全属性校验:
- 临时移除
created_at的验证和安全限制(如在 rules 中注释掉相关行); - 用
updateAll()直接更新数据库:YourModel::updateAll(['created_at' => '2025-01-01 10:00:00'], ['id' => 123]); - 更新后手动刷新模型实例,避免缓存脏数据。
本质上,created_at 不是“可编辑字段”,而是数据生命周期的锚点。改它不如厘清时间语义,加新字段更安全、更可维护。


















