Processing A Model Attribute Before Its Returned

I have a DB table with columns. This table has a model for it.

Now, a certain column, I want that when I reference it, say with:

[size="2"]




$some_model->certain_attr



[/size]

[size="2"]I want to do something with the attribute before its returned to the client who run this line of code.[/size]

[size=“2”]Now, since certain_attr is an attribute that has a column for it, I cannot create a ‘getter’ method that will be called, as done with virtual attributes. As detailed in this wiki article (see 'resolving conflicts" section), the check [/size]whether its a column for that model will be made first, and the value returned as is.

My solution as of now is to overwrite __get() in the certain model to change the exact precedence in which the value is checked.

EDIT: actually, what I change is that in this overwriting __get(), I first call the parent __get() but then searches for a ‘getter’ method and if it exists, I call it on the value returned from the parent __get().

Have overlooked a better solution?

Thanks!

you can map database value to attribute in afterFind and map it back to db value in beforeValidate or beforeSave, like this:




class Model extends CActiveRecord {

  public function afterFind() {

    //map database value to php value

    $this->attribute = unserialize( $this->attribute );

    parent::afterFind();

  }


  public function beforeSave() {

    //map php value to database value

    $this->attribute = serialize( $this->attribute );

    parent::beforeSave();

  }

  ...



First, thanks for the swift reply!

Next, this is a continuation of the same task I posted about yesterday and on which you’ve replied :slight_smile:

Indeed, its a matter of serialization and deserialization.

The problem is happening when this is the order of things:




// the fundamental problem is keeping both the db record and the 'session-cached' record in sync.

// for that, we've devised the following code that ensures it:

$profile = clone(Yii::app()->user->myProfile);

$profile->relevant_attr = $some_value;

if( $profile->save() ) {

   // only when the save() finished ok, *including validation*, we update the 'cached' version of the record

  Yii::app()->user->myProfile->relevant_attr = $profile->relevant_attr;

}



Now I already have the beforeSave() and afterFind() methods just as you describe, with the exact serialize() and unserialize() as ‘$some_value’ above is indeed an array.

The problem is that the value assigned in the last line to [size="2"]Yii::app()->user->myProfile->relevant_attr is the serialized array, as a result of the beforeSave() that did it.[/size]

I’m thinking about it now, maybe instead of doing this rather cumbersome juggling, I should just do in the last line:




Yii::app()->user->myProfile->relevant_attr = unserialize($profile->relevant_attr);



As the ‘session-cached’ profile record is considered to be ‘out of the DB’ therefore its content should be before-beforeSave()…

I think I kinda answered myself. [size="2"]You think otherwise?[/size]

[size="2"]Thanks again![/size]

[size="2"](Damn with this WYSWYG editor - it inserts some hidden html markups… .)[/size]

yep. I am always storing in session only values, not the whole active record object (Yii::app()->session[‘cache’] = $model->attributes).

thanks.