2013-08-27 4 views
6

Ich erhebe ein Yii-Ereignis auf beforeSave des Modells, das nur ausgelöst werden soll, wenn eine bestimmte Eigenschaft des Modells geändert wird.Yii bei der Aktualisierung, erkennen, ob eine bestimmte AR-Eigenschaft auf beforeSave() geändert wurde

Die einzige Möglichkeit, wie ich das jetzt machen kann, ist, ein neues AR-Objekt zu erstellen und die DB für das alte Modell mit dem aktuellen PK abzufragen, aber das ist nicht sehr gut optimiert.

Hier ist, was ich habe jetzt (beachten Sie, dass mein Tisch kein PK hat, deshalb habe ich von allen Attributen abfragen, außer der, die ich gegen bin im Vergleich - daher der unset-Funktion):

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(); 
} 

Gibt es einen besseren Ansatz? Vielleicht speichern Sie die alten Eigenschaften in einer neuen lokalen Eigenschaft in afterFind()?

Antwort

12

Sie müssen die alten Attribute in einer lokalen Eigenschaft in der AR-Klasse speichern, damit Sie jederzeit die aktuellen Attribute mit denen der alten vergleichen können.

Schritt 1. Fügen Sie eine neue Eigenschaft der AR-Klasse:

// Stores old attributes on afterFind() so we can compare 
// against them before/after save 
protected $oldAttributes; 

Schritt 2. Überschreiben Sie Yii's afterFind() und speichern Sie die ursprünglichen Attribute sofort nach dem Abrufen.

public function afterFind(){ 
    $this->oldAttributes = $this->attributes; 
    return parent::afterFind(); 
} 

Schritt 3. Vergleichen Sie die alten und neuen Attribute in beforeSave/afterSave oder anderswo in der AR-Klasse. Im folgenden Beispiel prüfen wir, ob die Eigenschaft 'level' geändert wurde.

public function beforeSave() 
{ 
    if(isset($this->oldAttributes['level']) && $this->level != $this->oldAttributes['level']){ 

      // The attribute is changed. Do something here... 

    } 

    return parent::beforeSave(); 
} 
+1

Dies ist in der Tat die einzige "sauber", wie es in Yü zu tun. Was ich getan habe, war eine abgeleitete ActiveRecord zu implementieren, die diese Funktionalität eingebaut hat und sie für alle meine Modelle verfügbar macht. Viel einfacher als es jedes Mal wieder zu tun. Ich gab auch Methoden wie "getIsChanged()" und "getChangedProperties()" und so weiter. – Blizz

0

Sie können alte Eigenschaften mit ausgeblendeten Feldern im Aktualisierungsformular speichern, anstatt das Modell erneut zu laden.

0

Gerade in einer Zeile

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

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

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

} 

In Ihrem Fall sollten Sie verwenden, wenn (key == $ 'Niveau') innerhalb von foreach

Verwandte Themen