Access Old Attribute Values In Ar Model

Hi,

Is there any way to access the old attribute values after using the setAttributes method to assign new values?

I need to update a field if only the users has input some new values. in the other hand if the field is empty, save the old value (which is set as empty by not entering any values by the user).

Check this extension. Even if you don’t use it all you might benefit learning from the “dirtyness” check source code.

Hello,

You may do like…

in controller.




public function actionUpdateTable()

{

   $modelObj = DemoTable::model()->find('id='.$_GET['id']);

   if(isset($_POST['DemoTable']) && $_POST['DemoTable'])

   {

       $modelObj->firstname = $_POST['DemoTable']['firstname'];

       $modelObj->lastname = $_POST['DemoTable']['lastname'];




       if($_POST['DemoTable']['city']!=="")

       {

           $modelObj->city= $_POST['DemoTable']['city'];

       }

       

       $modelObj->save();

   }

}



I wrote a basic history logging behavior which does this:




	private $oldAttributes;

	

	public function afterFind($event)

	{

		$this->oldAttributes = $this->getOwner()->getAttributes();

	}



If you made $oldAttributes public or wrote an accessor for it, this could work for you. After creating the behavior, you’d just include it in the models which need the functionality like this:




	public function behaviors()

	{

		return array(

			'ActiveRecordHistoryLogger'

				=> 'application.models.behaviors.ActiveRecordHistoryLogger',

		);

	}



replacing the name and path as appropriate.

Dear Friend

Declare a virtual property in the model.




public $oldRecord;



Overide the afterFind method of AR




public function afterFind()

    {

	$this->oldRecord=clone $this;

	parent::afterFind();		

    }



Now in controller in actionUpdate method, we can access the old values like below.




$model->oldRecord->password;

$model->oldRecord->name;



Regards.

Thank you all for replying.

In my case I think the way that seenivasan pointed out is the best option.

Cheers.

I know that this is a bit of an older post, but I wanted to offer a simpler solution that uses less memory.

The Yii AR models already store an array with the old values, so there is no need to clone them again. Simply access them like this:


$model->oldValues['attributeName']

For example in your User model you may want to make sure the password is hashed when updated.




public function beforeSave()

{

    if ($this->password != $this->oldValues['password']) { // password has changed, so we need to hash it.

        $this->password = CPasswordHelper::hashPassword($this->password,13);

    }


    return parent::beforeSave();

}



Thanks Robert,

It sounds good. I’ll give it a try soon :)