# CakePHP 4 Soft Delete

> A soft delete marks a record as no longer active or valid without deleting it from the database. Soft deletion is a widely used pattern applied for business applications.

- URL: http://codethepixel.com/cakephp-4-soft-delete
- Author: Asyraf Wahi Anuar (http://codethepixel.com/author/asyraf-wahi-anuar)
- Published: 2023-01-22
- Category: CakePHP
- Tested with: CakePHP 4.x
- Tags: CakePHP, Plugin, Soft Delete, Delete, Restore, Trash, useMuffin
- Reading time: 5 min

A soft delete marks a record as no longer active or valid without deleting it from the database. Soft deletion is a widely used pattern applied for business applications. It allows users to mark some records as deleted without erasure from the database. Effectively, the user prevents a soft-deleted record from being selected; meanwhile, all old records can still refer to it. Hard deletes are hard to recover if something goes wrong (application bug, bad migration, manual query, etc.). This usually involves restoring from a backup, and targeting only the data affected by the bad delete is hard. Soft deletes are easier to recover from once the user determines what happened. This tutorial will demonstrate how to apply the soft delete method in CakePHP 4 using '[useMuffin Trash](https://github.com/UseMuffin/Trash)' plugin.

## Installation

Download using composer:

```bash
$ composer require muffin/trash
```

Load the plugin:

```bash
$ cake plugin load Muffin/Trash
```

## Usage

You database should have DATETIME column 'deleted' or 'trashed'. If use different name, you need to identify the specific column name in behavior.

In the table(s) model, add the Trash behavior as shown below:

```php
$this->addBehavior('Muffin/Trash.Trash');
```

The behaviour will default auto-detect the **DATETIME **column used to track trashed (soft-deleted) records, but only if you use **deleted **or **trashed **names. Otherwise, you could customize that when adding the behaviour:

```php
$this->addBehavior('Muffin/Trash.Trash', [
    'field' => 'deleted_at'
]);
```

or, at the global level, in bootstrap.php:

```php
Configure::write('Muffin/Trash.field', 'deleted_at');
```

Add the following code in controller header:

```php
use Muffin\Trash\Model\Behavior\TrashBehavior;
use Cake\ORM\Entity;
```

To restore all trashed records, add the following function:

```php
public function restoreAllTrash()
{
    $this->Playgrounds->restoreTrash();
    $this->Flash->success(__('All records has been restored'));
    return $this->redirect(['action' => 'index']);
}
```

To restore a specific trashed entity, use the following function:

```php
public function restoreTrashEntity($id = null)
{
    $this->Playgrounds->restoreTrash(new Entity([
        'id' => $id,
    ], ['markNew' => false, 'markClean' => true]));
    
    return $this->redirect(['action' => 'find-only-trashed']);
}
```

To transfer all records to trash, use the following code. It will trash all records in the database:

```php
public function trashAll()
{
    $this->Playgrounds->trashAll('1 = 1');
    $this->Flash->success(__('All record has been deleted'));
    return $this->redirect(['action' => 'index']);
}
```

To list all trashed records, use the following code:

```php
public function findOnlyTrashed()
{
    $this->paginate = [
        'maxLimit' => 10,
    ];
    $playgrounds = $this->paginate($this->Playgrounds->find('onlyTrashed'));
    
    $this->set(compact('playgrounds'));
}
```

To empty the trashed records, use the following code. This action will hard-delete the records from the database.

```php
public function emptyTrash()
{
    $this->Playgrounds->emptyTrash();
    $this->Flash->success(__('Trash Empty'));
    return $this->redirect(['action' => 'find-only-trashed']);
}
```

That's all. Happy coding :)
