1

when a model attributes are edited or updated I do not want that record to updated. Instead a new record should be created and the old record should be disabled. Also I have another log table where the old record is saved.

My code is given below

public function afterSave($insert, $changedAttributes)
{


  if ($insert) {
           // Да это новая запись (insert)
            $model = new Test3log();
            $model->desc = $this->desc ;
            $model->id_old = $this->id;
            $model->isdisabled=1;
            $model->save();
        } else {

            $save = "";
            foreach ($changedAttributes as $change => $val) {
                if (trim($val) != trim($this->{$change})) {
                    $save .= $this->attributeLabels()[$change] . '[' . $val . '->' . $this->{$change} . "]\n";
                }
            }
            $xx =$this->getoldattributes();
            if ($save != "") {
                 //  Get Old data
                 // Get New data
                 // repl new record with old id
                 // repl old record with new id
                $modelnewline = new Test3();
                $modelnewline->desc = $xx['desc'];
                $modelnewline->id_old = $xx['id'];
                $modelnewline->id = NULL;
                $modelnewline->isdisabled = 1;
                $modelnewline->save();
                $newid = $modelnewline->id;
                $oldid =$this->id;
                $this->isdisabled=1;
                $this->id = $newid;
                $this->desc = $changedAttributes['desc'];
                $this->save(false);

             }
        }
        parent::afterSave($insert, $changedAttributes);
    }
Muhammad Omer Aslam
  • 22,976
  • 9
  • 42
  • 68

1 Answers1

0

Your question is too broad and you haven't mentioned what exactly is your current problem you are facing but considering you new to the community i will attempt to answer it in a way that you could translate it accordingly.

Above all, the problem you described needs to be implemented in your model's beforeSave() which is called at the beginning of inserting or updating a record, rather than afterSave() as your record will already be updated with the new values and you definitely don't want to do that.

As per your requirements.

when a model attributes are edited or updated I do not want that record to be updated. Instead, a new record should be created and the old record should be disabled. Also, I have another log table where the old record is saved.

So there are 3 main things when attributes change for the existing record

  • Disable the current record by updating status to 0.
  • Add a new Record holding the new values.
  • Add a new Record with the old values inside the backup or logs table.

I will not be adding the actual code as there isn't much information available regarding what models are interacted so looking at the requirements i will use the scenario where i will assume that i have books and whenever the name of the book is changed or updated it should add a new record with the new values and keep the old record as is changing the status column to 0 so that the book is disabled and backup the old values to BooksBackup table. So basically you will have a wireframe to adjust your code accordingly.

You can use the logic according to the models that you are using.

Below is the sample schema

  • Books model

    • name varchar(255)
    • status tinyint(1)
  • BooksBackup model

    • id int(11)
    • book_id int(11)
    • name varchar(255)

I will add the following beforeSave() function in my Books Model

public function beforeSave($insert) {
    if( !parent::beforeSave($insert) ){
        return false;
    }

    //your custom code
    if( !$insert ){

        $ifAttributesChanged = (!empty($this->dirtyAttributes) );

        //if attributes were changed
        if( $ifAttributesChanged ){

            //add new record with the new values
            $book = new self();
            $book->attributes = $this->attributes;
            $book->save();

            //add back the old values of the changed attributes 
            //to the current record so nothing is changed for the current record
            foreach( $this->dirtyAttributes as $attribute => $value ){
                $this->$attribute = $this->oldAttributes[$attribute];
            }

            //disable the current record
            $this->status = 0;

            //backup old record
            $backup = new BackupBooks();
            $backup->book_id = $this->id;
            $backup->name = $this->name;
            $backup->save();
        }
    }
    return true;
}
Muhammad Omer Aslam
  • 22,976
  • 9
  • 42
  • 68
  • Thank you very much. You have clearly understood my requirement. In short my requirement is to keep history of my records and audit trail without using extensions for my application. I will try your code as soon as possible. after reading your I believe it will work. I was writing my code in aftersave() function. Thank you very much. – Ignatius Abraham Aug 20 '18 at 00:51
  • Hi Muhammad Omer Aslam I have found one issue.- if Book had an PK then I have added a line $book->id = null; otherwise it will be an violation error. otherwise worked as a charm. Hopefully I can extend this solution to my related tables. thanks – Ignatius Abraham Aug 20 '18 at 07:09
  • sorry but i couldnt understand exactly what problem you are having, i tested this solution on my end and it works fine without any problem, @IgnatiusAbraham – Muhammad Omer Aslam Aug 20 '18 at 07:11
  • do mark the answer as correct if it works for you @IgnatiusAbraham – Muhammad Omer Aslam Aug 20 '18 at 07:12