Yii 更新时,检测是不是在 beforeSave() 上更改了特定的 AR 属性
Posted
技术标签:
【中文标题】Yii 更新时,检测是不是在 beforeSave() 上更改了特定的 AR 属性【英文标题】:Yii on update, detect if a specific AR property has been changed on beforeSave()Yii 更新时,检测是否在 beforeSave() 上更改了特定的 AR 属性 【发布时间】:2013-08-27 09:16:36 【问题描述】:我在模型的 beforeSave 上引发了一个 Yii 事件,只有在模型的特定属性发生更改时才会触发该事件。
目前我能想到的唯一方法是创建一个新的 AR 对象并使用当前 PK 查询旧模型的数据库,但这并没有得到很好的优化。
这就是我现在所拥有的(请注意,我的表没有 PK,这就是我查询所有属性的原因,除了我要比较的属性 - 因此是 unset
函数):
public function beforeSave()
if(!$this->isNewRecord) // only when a record is modified
$newAttributes = $this->attributes;
unset($newAttributes['level']);
$oldModel = self::model()->findByAttributes($newAttributes);
if($oldModel->level != $this->level)
// Raising event here
return parent::beforeSave();
有没有更好的方法?也许将旧属性存储在 afterFind()
的新本地属性中?
【问题讨论】:
【参考方案1】:您需要将旧属性存储在 AR 类的本地属性中,以便您可以随时将当前属性与旧属性进行比较。
第 1 步。向 AR 类添加新属性:
// Stores old attributes on afterFind() so we can compare
// against them before/after save
protected $oldAttributes;
第 2 步。覆盖 Yii 的afterFind()
并在检索到原始属性后立即存储。
public function afterFind()
$this->oldAttributes = $this->attributes;
return parent::afterFind();
第 3 步。比较 beforeSave/afterSave
或 AR 类中您喜欢的任何其他地方的新旧属性。在下面的示例中,我们正在检查名为 'level' 的属性是否已更改。
public function beforeSave()
if(isset($this->oldAttributes['level']) && $this->level != $this->oldAttributes['level'])
// The attribute is changed. Do something here...
return parent::beforeSave();
【讨论】:
这确实是 Yii 中唯一“干净”的方式。我所做的是实现一个派生的 ActiveRecord,它内置了该功能,并使其可用于我的所有模型。比每次都做一遍容易得多。我还给了它“getIsChanged()”和“getChangedProperties()”等方法。【参考方案2】:就在一行
$changedArray = array_diff_assoc($this->attributes, $this->oldAttributes);
foreach($changedArray as $key => $value)
//What ever you want
//For attribute use $key
//For value use $value
在您的情况下,您想在 foreach 中使用 if($key=='level')
【讨论】:
【参考方案3】:Yii 1.1: mod-active-record@yiiframework.com
或Yii Active Record instance with "ifModified then ..." logic and dependencies clearing gist.github.com
【讨论】:
【参考方案4】:您可以在更新表单中存储带有隐藏字段的旧属性,而不是再次加载模型。
【讨论】:
以上是关于Yii 更新时,检测是不是在 beforeSave() 上更改了特定的 AR 属性的主要内容,如果未能解决你的问题,请参考以下文章
Parse Serve 成功 beforeSave 为某些用户返回“找不到对象”错误