How to compare two Active Record Models

Hey,

i have written a small behavior that hopefully can become useful for someone:




class CCompare extends CActiveRecordBehavior

{

  public function compare($other) {

    if(!is_object($other))

      return false;


    // does the objects have the same type?

    if(get_class($this->owner) !== get_class($other))

      return false;


    $differences = array();


    foreach($this->owner->attributes as $key => $value) {

      if($this->owner->$key != $other->$key)

        $differences[$key] = array(

            'old' => $this->owner->$key,

            'new' => $other->$key);

    }


    return $differences;

  }

}



Copy this Code as a file in your components/ directory and configure it like this in your AR Model:




  public function behaviors()  {

    return array( 'CCompare'); // <-- and other behaviors your model may have

  }



After that, you can use it this way:




$example_original = Demomodel1::model()->findByPk(5);

$example_comparison = Demomodel1::model()->findByPk(6);


$differences = $example_original->compare($example_fake);



After that, you will have all differences between your Original and Compared model.

If you provide another type of model to the compare function, false is returned.

If the models have the same attributes, only the Primary Key is returned, since it is the only attribute that differs.

Last but not least, if the Models are absolutely the same, an empty array is returned, since there are no differences.

will be! thanks

thanks for sharing

Excellent idea, this is very useful, only issue is that only classes that start with "C" are reserved for Yii classes.

Late Congratulations @thyseus!

In my case, has to compare two model’s item to manage whether is new or update register.

Using @thyseus behavior implementation I had a little problem with model validation producing by behavior.

Then, I resolve this thanks to Dana Luther and his post "How to use Behaviors in Yii".

She said, and I confirmed that this work, …

.

And so I did…


                    	$modelLodging->attachBehavior( 

                        	'CCompare', 

                        	'application.components.behaviors.CCompare'

                    	);

                    	$modelLodging_Save->attachBehavior( 

                        	'CCompare', 

                        	'application.components.behaviors.CCompare'

                    	);

                    	//Update only when are equals:

                    	if($modelLodging->compare($modelLodging_Save))

                    	{

Thanks @thyseus and Dana Luther! :D