[Solved]Is it possible to get old value in beforeSave()

in the CActiveRecord class, I create a beforeSave() function. In here I want to get the old value of the model. Is there any way to do it? thanks before

You can load it from the database, using another instance of the AR. Your you could clone your original instance before modifying its fields.

I have exactly the same logic for tracking changes to AR.


            

public function beforeSave()

    {

        $this->changesText = '';

        $curr = self::findByPk($this->id);

        if($curr)

        {

            if($curr->name != $this->name)

                $this->changesText .= "Change name to \"{$this->name}\".";

            if($curr->region_id != $this->region_id)

                $this->changesText .= "Change region to \"{$this->region->name}\".";  

..............

I see. I’ve got your logic…

Thank you very much, phreak and soso :)

In my opinion, this is bad practice, as the model you load from DB really should be the same as the one you are currently in. It’s just because Yii haven’t implemented the Identity Map pattern yet: http://en.wikipedia.org/wiki/Identity_map.

I know this is an old thread, but I wanted to note how I am doing this - for people that are still searching like I was. I, like most of us, have a base class that I use for all my models that extends CActiveRecord. In that class, I have a get/set for OldAttributes. In the init, I hook into the OnAfterFind event, and add a line of code that populates my old attributes. It’s simple, yet effective, and has pretty low overhead - with no second database query. Here’s a simplified version of the code I’m using:




class MyModel extends CActiveRecord

{

    private $_oldAttributes = array();

    public function setOldAttributes($value)

    {

        $this->_oldAttributes = $value;

    }

    public function getOldAttributes()

    {

        return $this->_oldAttributes;

    }


    public function init()

    {

        $this->attachEventHandler("onAfterFind", function ($event)

        {

            $event->sender->OldAttributes = $event->sender->Attributes;

        }

    }

}



From there, I have access via:




// Inside the model itself

$OldColumnInfo = $this->OldAttributes['ColumnName'];


// Via an instance

$OldColumnInfo = $MyModelInstance->OldAttributes['ColumnName'];



Thanks AirborneAgain.

I think using "afterFind" event is a very elegant solution.

This is exactly what I do in a base class all my AR models are extending. I’ve released it as an extension - PcBaseArModel. Perhaps it will be useful for you to examine it. See there isAttributeDirty().

Dear Friends

We can do the things in the following way.




class User extends CActiveRecord

{  

    public $oldRecord;


    public function afterFind()

    {

		$this->oldRecord=clone $this;

                return parent::afterFind();	

    }



Now We can access the old attributes in beforeSave method.




$this->oldRecord->password;



I am not sure whether cloning the objects in such a way is advisable.

in yii2

$this->getDirtyAttributes();

Ref: http://www.yiiframework.com/doc-2.0/yii-db-baseactiverecord.html#$dirtyAttributes-detail

very useful. thank you

How to use this method?