Yii在更新时,检测beforeSave()上是否更改了特定的AR属性


Yii on update, detect if a specific AR property has been changed on beforeSave()

我在模型的beforeSave上引发了一个Yii事件,只有当模型的特定属性发生更改时才会触发该事件。

目前我能想到的唯一方法是创建一个新的AR对象,并使用当前PK在DB中查询旧模型,但这并没有得到很好的优化。

以下是我现在所拥有的(请注意,我的表没有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()中的新本地属性中?

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

仅在一行中

$changedArray=array_diff_assoc($this->属性,$this->oldAttributes);

foreach($changedArray as $key => $value){
  //What ever you want 
  //For attribute use $key
  //For value use $value
}

在您的情况下,您希望在foreach 内部使用if($key=='level')

Yii 1.1:yiiframework.com 上的mod活动记录

或在gist.github.com 上清除带有"ifModified then…"逻辑和依赖关系的Yii活动记录实例

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