Yii表单模型不自动处理时间戳字段,需手动配置rules()规则、重写beforeValidate()或在控制器中赋值,并结合scenario控制不同场景下的时间戳行为。

Yii框架中表单模型(Form Model)本身不自动处理时间戳字段,比如 created_at、updated_at,这些字段默认不会被赋值或过滤——它不像 ActiveRecord 那样内置时间戳行为。要让表单模型支持时间戳的自动填充、验证或安全过滤,需手动配置规则和逻辑。
时间戳字段需显式声明并加入安全规则
表单模型中若定义了 $created_at、$updated_at 等属性,它们默认不属于“安全属性”(safe attributes),load() 方法不会自动赋值。必须在 rules() 中明确标记为 'safe' 或指定其他验证规则:
- 用
'safe'允许直接赋值(适合前端传入时间,如创建时间由用户选择):['created_at', 'safe'] - 用
'datetime'验证格式,并指定 PHP DateTime 格式(如'php:Y-m-d H:i:s'):['created_at', 'datetime', 'format' => 'php:Y-m-d H:i:s'] - 若想由服务端自动设值(如创建时填当前时间),就不该让用户提交,也不应出现在
rules()中;而应在beforeValidate()或控制器中手动赋值
自动填充时间戳的两种常用方式
表单提交时不想依赖前端传时间,而是由系统注入,推荐以下做法:
- 在模型类中重写
beforeValidate()方法:
若$this->created_at为空,则设为date('Y-m-d H:i:s');
若$this->updated_at始终更新,也在此处统一赋值 - 在控制器中手动设置(更清晰、易测试):
$model->created_at = date('Y-m-d H:i:s');$model->updated_at = date('Y-m-d H:i:s');
再调用$model->load()和$model->validate()
防止时间戳被恶意篡改(安全过滤)
如果时间戳字段不应由用户控制(例如后台审核时间、系统记录时间),就绝不能放进 rules() 的 'safe' 列表,也不能允许通过 load() 赋值:
- 移除相关字段的
'safe'规则 - 在
rules()中使用'default'规则屏蔽用户输入:['created_at', 'default', 'value' => null]或固定值 - 更严格的做法:不在表单模型中定义这些字段,仅在关联的 ActiveRecord 中处理时间戳逻辑
与场景(scenario)配合控制时间戳行为
不同操作对时间戳要求不同,比如“新建”需填 created_at,“编辑”需更新 updated_at 但不允许改 created_at:
- 定义多个场景:
public function scenarios() { return [ 'create' => ['contact', 'email', 'created_at'], 'update' => ['contact', 'email', 'updated_at'] ]; } - 在
rules()中按场景限定:['created_at', 'required', 'on' => 'create']['created_at', 'safe', 'on' => 'update']→ 实际应禁用,此处仅为说明逻辑 - 控制器中务必显式设置:
$model->scenario = 'create';


















