yii: soft delete

by prettyscripts on 2011-03-28 12:31

phpyii

as with most of my projects, i do not want to physically delete most records so that they can be re-instated later.

however, since i can't seem to find any info regarding this topic, i guess soft delete is not available in yii. you need to implement this yourself.

the code in this post is based on this forum post and the code for CTimestampBehavior. it will timestamp a deleted field to mark it's deleted. by default the field name is delete_time but can be set to a different name.

create a soft delete behavior

create a new file in /path/to/protected/components/behaviors/SoftDeleteBehavior.php:

PHP:

class SoftDeleteBehavior extends CActiveRecordBehavior {
    public $deleteAttribute 'deleted_time';
    public $timestampExpression null;
 
    public function beforeDelete($event) {
        if ($this->deleteAttribute !== null) {
            $this->getOwner()->{$this->deleteAttribute} = $this->getTimestampByAttribute($this->deleteAttribute);
            $this->getOwner()->save();
 
            // prevent real deletion of record from database
            $event->isValid false;
        }
    }
 
    // copy codes from the same function names from
    // /path/to/framework/zii/behaviors/CTimestampBehavior.php
    protected function getTimestampByAttribute($attribute) {
        // paste function code here
    }
    protected function getTimestampByColumnType($columnType) {
        // paste function code here
    }
}

add a behavior to ActiveRecord

in /path/to/protected/models/Model.php:

PHP:

class <name of model> extends CActiveRecord {
    public function behaviors {
        return array(
            'SoftDeleteBehavior' => array(
                'class' => 'application.components.behaviors.SoftDeleteBehavior',
                'deleteAttribute' => 'deleted_date'// optional, default is 'deleted_time'
                'timestampExpression' => 'date("Y-m-d H:i:s");',
            ),
        );
    }
}

re-instating deleted record

add a reinstate function to the behavior defined above:

PHP:

class SoftDeleteBehavior extends CActiveRecordBehavior {
    ....
    function reinstate() {
        if ($this->deleteAttribute !== null) {
            if ($this->getOwner()->{$this->deleteAttribute} !== null) {
                $this->getOwner()->{$this->deleteAttribute} = null;
                $this->getOwner()->save();
            }
        }
    }
    ....
}

in controller file, add a new reinstate action:

PHP:

class MyController extends Controller {
    public function actionReinstate($id) {
        $this->loadModel($id)->reinstate();
    }
}

notes

this has not been tested with deleting multiple records.

i'm still not proficient with yii. appreciated any comments and feedbacks to improve codes in this post, or if there's a better way to do this.