determine which attributes are changed of an ActiveRecord


(Jeanluca) #1

Hi All

Is it possible to check if an attribute is changed or not, for example:




if ( $user->isChanged('address') ) { .... }



If you would use lazy loading a test like




if ( isset($user->Company) ) { ... }



would still require loading the Company, and its still unknown if the Company is changed (an object with a different primary key) or not!

If something like this is not implemented, any suggestions how it can be solved ?

cheers


(Matteo Falsitta) #2

Maybe the new Query caching can fit you.

You can cache the query for retrive the company, if the company changes Yii will repeat the query.


(mbi) #3

save old attributes of AR in a variable in AR::afterFind()




public function afterFind()

{

    $this->_oldAttrbiutes = $this->attributes;

}



compare and handle in AR::beforeSave()


(Jeanluca) #4

Thanks for the answers. But I still have a problem. Suppose I have a relation as follows:

User.php:


'address'	=> array(self::BELONGS_TO, 'Company', 'company_id'),



So when I do:




$u = User::model()->findByPk(10) ;

..... do some undetermined stuff here .....


if ( isset($u->company) ) {  // load the Company object!!

    $u->company_id = $u->company->id ;

}



How do I tell if the Company object was set/changed. For example, if nothing happend during the … undetermined stuff… to the company, the above if-statement will have the result that the company is loaded from the database. Any suggestions ?


(el chief) #5

not sure what you’re asking. please rephrase


(Jacob Moen) #6

I think that maybe you could make good use of one of the audit extensions:

http://www.yiiframework.com/search/?q=audit&type=extension〈=

It basically allows you to track changes to your models.

Perfect for the job, I’d think. :)


(Jeanluca) #7

I actually wanted to implement something like this into an extension/behavior ?

UPDATE: I guess the only solution is maybe to override the magic method: __get/__set ? Can this be done with an extension/behavior?

UPDATE: overriding __get/__set in a behavior doesn’t seem to work :(


(Jeanluca) #8

The problem can be defined as follows: given an object $user (which BELONGS_TO a Company)

The only thing you know about this $user is that some attributes have changed.

Now, if the company has changed, you have to add its primaryKey value to company_id like:




if ( isset($user->company) ) {

   $user->company_id = $user->company->id

}

$user->save() ;



Easy, but if the company didn’t change, you have just done some useless DB queries, which might not be good for performance!

This is also a problem with other relations! There seems to be no way to tell which attributes have changed!

Cheers


(Pedro) #9

public function isChanged($atributo)
{
return (isset($this->getDirtyAttributes()[$atributo]));
}