Yii when updating, determine if a specific AR property has been changed to beforeSave ()

I raise the Yii event on the beforeSave of the model, which should only fire when a specific property of the model changes.

The only way I can think of how to do this at the moment is to create a new AR object and query DB for the old model using the current PK, but this is not very optimized.

Here is what I have right now (note that my table does not have a PC, so I request for all the attributes except the one with which I compare - this is where the unset function 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(); } 

Is there a better approach? Perhaps saving old properties in a new local property in afterFind() ?

+6
source share
4 answers

You need to store the old attributes in a local property in the AR class so that you can compare the current attributes with these old ones at any time.

Step 1 Add a new property to the AR class:

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

Step 2 Override Yii afterFind() and save the original attributes immediately after receiving them.

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

Step 3 Compare the old and new attributes in beforeSave/afterSave or anywhere else that you like inside the AR class. In the example below, we check to see if the property named "level" has changed.

 public function beforeSave() { if(isset($this->oldAttributes['level']) && $this->level != $this->oldAttributes['level']){ // The attribute is changed. Do something here... } return parent::beforeSave(); } 
+12
source

You can store old properties with hidden fields inside the update form, and not load the model again.

0
source

In only one line

$ 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 } 

In your case, you want to use if ($ key == 'level') inside foreach

0
source

Source: https://habr.com/ru/post/952573/


All Articles