Yii2:afterFind()排除属性及时间戳保存异常问题咨询
这个问题我之前也碰到过,核心原因是你在afterFind()里直接修改了模型对应数据库字段的属性值,导致保存时框架把修改后的格式化日期当成新值提交了。下面给你两个靠谱的解决思路,还有关于排除属性的方法:
解决保存原始时间戳的问题
方法1:使用虚拟属性存储格式化后的日期
不要直接修改created_at和updated_at这两个原始字段,而是在Model里新增两个虚拟属性来存格式化后的日期,这样原始字段始终保持时间戳状态,保存时就不会被覆盖了。
步骤如下:
- 在你的
Project模型中添加虚拟属性:
// 虚拟属性,不对应数据库字段 public $formattedCreatedAt; public $formattedUpdatedAt; public function afterFind() { parent::afterFind(); // 别忘了调用父类方法 // 给虚拟属性赋值,原始字段created_at/updated_at保持不变 $this->formattedCreatedAt = date('Y-m-d', $this->created_at); $this->formattedUpdatedAt = date('Y-m-d', $this->updated_at); }
- 在
index.php的GridView中,用虚拟属性来展示日期:
'columns' => [ // 其他列... [ 'label' => '创建时间', 'value' => 'formattedCreatedAt', ], [ 'label' => '更新时间', 'value' => 'formattedUpdatedAt', ], // 操作列... ],
方法2:直接在GridView中格式化日期(更简洁)
如果不需要在Model层复用格式化后的日期,完全可以跳过afterFind()的处理,直接在GridView的列配置中做格式化,这样模型的原始属性根本不会被修改,从根源避免问题:
'columns' => [ // 其他列... [ 'attribute' => 'created_at', 'value' => function ($model) { return date('Y-m-d', $model->created_at); }, 'label' => '创建时间', ], [ 'attribute' => 'updated_at', 'value' => function ($model) { return date('Y-m-d', $model->updated_at); }, 'label' => '更新时间', ], // 操作列... ],
在afterFind()中排除指定属性的方法
如果你的afterFind()里有批量处理属性的逻辑,想要跳过某些指定属性,可以通过定义排除列表来过滤:
public function afterFind() { parent::afterFind(); // 定义要排除的属性名 $excludeAttributes = ['created_at', 'updated_at', 'status']; // 遍历模型属性时跳过排除项 foreach ($this->attributes as $attr => $value) { if (in_array($attr, $excludeAttributes)) { continue; // 跳过排除的属性 } // 这里写你的属性处理逻辑 } }
如果只是单独处理某些属性,更推荐直接明确指定要处理的属性(比如只处理title、content等),这样比排除列表更直观,也不容易出错。
内容的提问来源于stack exchange,提问作者Pravinraj Venkatachalam
相关产品推荐
相关产品推荐

