Sunday, January 12, 2014

Cascade delete in Yii model by overriding beforeDelete() and afterDelete() method

Yii provides Cascade using relations with the cascade constraint defined in database, which allows the user to delete cascade data when a model is deleted. However, in some cases, the user may want to perform this on his own (e.g. there may be some sophisticated conditioning involved during the cascade delete, or other resources such as images to be deleted associated with the model). In such a case, the user can override the beforeDelete() and afterDelete() method to perform the clean up (e.g. delete images and cascaded objects associated with the deleted model). Suppose we have a model class Project, and we want to delete a set of users as well as an image associated with the deleted Project model:

Step 1: Override beforeDelete()

Add a variable idCache to the User model class in protected/models/User.php:
private $idCache;
Next override the beforeDelete() method to assign User->id to idCache:
public function beforeDelete()
{
 $this->idCache = $this->id;

 return parent::beforeDelete();
}
The purpose of having idCache is to cache the User->id attribute in the beforeDelete() method and use it in the afterDelete() method (since the $User->id will no longer be available in the afterDelete() method

Step 2: Override afterDelete()

Next we will delete the associated users and image to the deleted Project model by overriding the afterDelete() method:
public function afterDelete()
{
 $criteria = new CDbCriteria(array(
   'condition' => 'project_id=:projectId',
   'params' => array(
    ':projectId' => $this->idCache),
  ));

 $users_associated_with_project = User::model()->findAll($criteria);

 foreach ($users_associated_with_project as $user)
 {
  $user->delete();
 }
 
 $filename=$this->getImagePath($this->idCache);
 if(file_exists($filename))
 {
  unlink($filename);
 }

 parent::afterDelete();
}

No comments:

Post a Comment