PHPackages                             notch/deleted-models - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. notch/deleted-models

ActiveLibrary[Database &amp; ORM](/categories/database)

notch/deleted-models
====================

Automatically copy deleted records to a separate table

1.0(2y ago)011MITPHPPHP ^8.1|^8.2|^8.3

Since Apr 8Pushed 2y agoCompare

[ Source](https://github.com/chapdel/deleted-models)[ Packagist](https://packagist.org/packages/notch/deleted-models)[ Docs](https://github.com/spatie/laravel-deleted-models)[ RSS](/packages/notch-deleted-models/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (2)Versions (2)Used By (0)

Automatically copy deleted records to a separate table
======================================================

[](#automatically-copy-deleted-records-to-a-separate-table)

[![Latest Version on Packagist](https://camo.githubusercontent.com/3e0f0d56aebf37a5c550d52b72fe85102d21f56c7a138a3b54ad06b2227106a8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f6c61726176656c2d64656c657465642d6d6f64656c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-deleted-models)[![GitHub Tests Action Status](https://camo.githubusercontent.com/73b7c034df09d8093e4543aa00202a9096cdaa8488488946de0cfbe064b6bb10/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7370617469652f6c61726176656c2d64656c657465642d6d6f64656c732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/spatie/laravel-deleted-models/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/4a437f739990b94db3646698d747ac6539513e09ca1aebdf459e8032ca52fed8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7370617469652f6c61726176656c2d64656c657465642d6d6f64656c732f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/spatie/laravel-deleted-models/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/ac538cbf4ee5e879d84e249cdc6fb934702485ff982e53ee9612f0fb9b0b5c10/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f6c61726176656c2d64656c657465642d6d6f64656c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-deleted-models)

When deleting an Eloquent model, this package will copy the attributes of that model to a new table called `deleted_models`. You can view this as a sort of "Recycle bin for models".

```
$blogPost = BlogPost::find(5); // an Eloquent model

$blogPost->delete(); // values will be copied to the `deleted_models` table.
```

To restore a previous model you can call `restore` and pass the id.

```
$blogPost = BlogPost::restore(5); // $blogPost will be restored and returned
```

This way of preserving information when deleting can be seen as an alternative to soft deletes. You can read more on the trade-offs [in this blog post](https://freek.dev/2416-a-package-to-automatically-copy-deleted-records-to-a-separate-table).

Support us
----------

[](#support-us)

[![](https://camo.githubusercontent.com/efe3d0a77970b0945b7d18c574c7c610eef9e482db3061ad764a584a23f0a4f2/68747470733a2f2f6769746875622d6164732e73332e65752d63656e7472616c2d312e616d617a6f6e6177732e636f6d2f6c61726176656c2d64656c657465642d6d6f64656c732e6a70673f743d31)](https://spatie.be/github-ad-click/laravel-deleted-models)

We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require spatie/laravel-deleted-models
```

To create the `deleted_models` table, you can publish and run the migrations with:

```
php artisan vendor:publish --tag="deleted-models-migrations"
php artisan migrate
```

Optionally, you can publish the config file with:

```
php artisan vendor:publish --tag="deleted-models-config"
```

This is the contents of the published config file:

```
return [
    /*
     * The model uses to store deleted models.
     */
    'model' => Spatie\DeletedModels\Models\DeletedModel::class,

    /*
     * After this amount of days, the records in `deleted_models` will be deleted
     *
     * This functionality uses Laravel's native pruning feature.
     */
    'prune_after_days' => 365,
];
```

The pruning of the `deleted_models` table depends on Laravel's native pruning feature. Don't forget to schedule the `model:prune` as instructed [in Laravel's docs](https://laravel.com/docs/9.x/eloquent#pruning-models).

```
$schedule->command('model:prune', [
    '--model' => [\Spatie\DeletedModels\Models\DeletedModel::class],
])->daily();
```

Usage
-----

[](#usage)

You should add the `KeepsDeletedModels` trait to all models whose attributes should be written to `deleted_models` whenever the model is deleted.

```
use Illuminate\Database\Eloquent\Model;
use Spatie\DeletedModels\Models\Concerns\KeepsDeletedModels;

class BlogPost extends Model
{
    use KeepsDeletedModels;
}
```

With this in place, the attributes will be written to `deleted_models` when the model is deleted.

```
$blogPost = BlogPost::find(5);

$blogPost->delete(); // values will be copied to the `deleted_models` table.
```

To restore a previous model you can call `restore` and pass the id.

```
$blogPost = BlogPost::restore(5); // $blogPost will be restored and returned
```

If the model to be restored can't be found in the `deleted_models` table, a `Spatie\DeletedModels\Exceptions\NoModelFoundToRestore` exception will be thrown.

### Restoring without saving

[](#restoring-without-saving)

To restore in memory, without actually saving it, you can call `makeRestored`. Keep in mind that calling this method will also remove the record in the `deleted_models_table`.

```
// $blogPost will be return, but it is not saved in the db yet
$blogPost = Blogpost::makeRestored($id);

$blogPost->save();
```

If the model to be restored can't be found in the `deleted_models` table, `null` will be returned by `makeRestored`.

### Restoring without emitting events

[](#restoring-without-emitting-events)

By default, the `Spatie\DeletedModels\Events\RestoringDeletedModelEvent` and `Spatie\DeletedModels\Events\DeletedModelEvent` will be dispatched when calling `restore` on a model.

If you don't want these events to be dispatched, call `restoreQuietly`.

```
BlogPost::restoreQuietly(); // no events will be dispatched
```

### Customizing the restore process

[](#customizing-the-restore-process)

#### Using closures passed to `restore`

[](#using-closures-passed-to-restore)

The `restore` function accepts a callable as the second argument. The `beforeSaving` callable will be executed when the restored model was created in memory, but before saving it in the db.

```
BlogPost::restore(5, function(BlogPost $post, DeletedModel $deletedModel) {
    $post->title = "{$post->title} (restored)";
})
```

#### Using methods on the model

[](#using-methods-on-the-model)

If you need to run some logic to before and after restoring a model, you can implement `beforeRestoringModel` and `afterRestoringModel` on your model.

```
use Illuminate\Database\Eloquent\Model;
use Spatie\DeletedModels\Models\Concerns\KeepsDeletedModels;

class BlogPost extends Model
{
    use KeepsDeletedModels;

    public static function beforeRestoringModel(DeletedModel $deletedModel): void
    {
        // this will be executed right before restoring a model
    }

    public static function afterRestoringModel(
        Model $restoredMode,
        DeletedModel $deletedModel
    ): void
    {
        // this will be executed right after restoring a model
    }
}
```

To determine which attributes and values should be kept in `deleted_models`, you can implement `attributesToKeep`

```
use Illuminate\Database\Eloquent\Model;
use Spatie\DeletedModels\Models\Concerns\KeepsDeletedModels;

class BlogPost extends Model
{
    use KeepsDeletedModels;

    public function attributesToKeep(): array
    {
        // here you can customize which values should be kept. This is
        // the default implementation.

        return $this->toArray();
    }
}
```

### Pruning deleted models

[](#pruning-deleted-models)

After a while, the `deleted_models` table can become large. The `DeletedModel` implements [Laravel's native `MassPrunable` trait](https://laravel.com/docs/9.x/eloquent#pruning-models).

You can configure the number of days records in the `deleted_models` will be pruned in the `prune_after_days` key of the `deleted-models.php` config file. By default, all deleted models will be kept for 365 days.

Don't forget to schedule the `model:prune` as instructed [in Laravel's docs](https://laravel.com/docs/9.x/eloquent#pruning-models).

### Low-level customization of the delete and restoration process

[](#low-level-customization-of-the-delete-and-restoration-process)

The `DeletedModel` model implements most logic to keep and restore deleted models. You can modify any of the behaviour by creating a class that extends `Spatie\DeletedModels\Models\DeletedModel`. You should put the class name of your extended class in the `model` key of the `deleted-models.php` config file.

With this in place you can override any of the methods in `DeletedModel`.

```
use Spatie\DeletedModels\Models\DeletedModel;

class CustomDeletedModel extends DeletedModel
{
    protected function makeRestoredModel(string $modelClass): mixed
    {
        // add custom logic

        return parent::makeRestoredModel($modelClass)
    }
}
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Freek Van der Herten](https://github.com/freekmurze)
- [All Contributors](../../contributors)

This package was inspired by these two blog posts:

- [Easy, alternative soft deletion](https://brandur.org/fragments/deleted-record-insert)
- \[this one\](Soft Deletion Probably Isn't Worth It).

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 72.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

770d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20987014?v=4)[Chapdel KAMGA](/maintainers/chapdel)[@chapdel](https://github.com/chapdel)

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (80 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (11 commits)")[![stfndamjanovic](https://avatars.githubusercontent.com/u/22433990?v=4)](https://github.com/stfndamjanovic "stfndamjanovic (7 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (6 commits)")[![riasvdv](https://avatars.githubusercontent.com/u/3626559?v=4)](https://github.com/riasvdv "riasvdv (3 commits)")[![Nielsvanpach](https://avatars.githubusercontent.com/u/10651054?v=4)](https://github.com/Nielsvanpach "Nielsvanpach (2 commits)")[![manadinho](https://avatars.githubusercontent.com/u/18038023?v=4)](https://github.com/manadinho "manadinho (1 commits)")[![chapdel](https://avatars.githubusercontent.com/u/20987014?v=4)](https://github.com/chapdel "chapdel (1 commits)")

---

Tags

spatielaravellaravel-deleted-models

### Embed Badge

![Health badge](/badges/notch-deleted-models/health.svg)

```
[![Health](https://phpackages.com/badges/notch-deleted-models/health.svg)](https://phpackages.com/packages/notch-deleted-models)
```

###  Alternatives

[spatie/laravel-backup

A Laravel package to backup your application

6.0k21.8M191](/packages/spatie-laravel-backup)[spatie/laravel-deleted-models

Automatically copy deleted records to a separate table

409109.8k4](/packages/spatie-laravel-deleted-models)[spatie/laravel-model-flags

Add flags to Eloquent models

4301.1M1](/packages/spatie-laravel-model-flags)[spatie/laravel-sql-commenter

Add comments to SQL queries made by Laravel

1931.4M1](/packages/spatie-laravel-sql-commenter)[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4802.8M8](/packages/dyrynda-laravel-model-uuid)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
