Yii on update,检测onSave()上是否更改了特定的AR属性

时间:2013-08-27 09:16:36

标签: php yii before-save

我在模型的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()

中的新本地属性中

4 个答案:

答案 0 :(得分:13)

您需要将旧属性存储在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();
}

答案 1 :(得分:1)

答案 2 :(得分:1)

只需一行

  

$ changedArray = array_diff_assoc($ this-> attributes,   $这 - > oldAttributes);

foreach($changedArray as $key => $value){

  //What ever you want 
  //For attribute use $key
  //For value use $value

}

在你的情况下,你想在foreach中使用 if($ key =='level')

答案 3 :(得分:0)

您可以在更新表单中存储隐藏字段的旧属性,而不是再次加载模型。