【问题标题】: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() 的新本地属性中?

【问题讨论】:

    标签: php yii before-save


    【解决方案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】:
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-18
        • 1970-01-01
        • 2013-11-02
        • 1970-01-01
        • 2021-10-21
        • 2013-06-14
        • 1970-01-01
        相关资源
        最近更新 更多