PHPackages                             spatie/laravel-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. spatie/laravel-deleted-models

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

spatie/laravel-deleted-models
=============================

Automatically copy deleted records to a separate table

1.2.0(2mo ago)409109.8k—4.8%26[1 PRs](https://github.com/spatie/laravel-deleted-models/pulls)4MITPHPPHP ^8.4CI passing

Since Jan 13Pushed 1mo ago3 watchersCompare

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

READMEChangelog (10)Dependencies (23)Versions (19)Used By (4)

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

64

—

FairBetter than 99% of packages

Maintenance88

Actively maintained with recent releases

Popularity53

Moderate usage in the ecosystem

Community27

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 60.5% 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

Every ~82 days

Recently: every ~168 days

Total

15

Last Release

73d ago

Major Versions

0.0.5 → 1.0.02023-01-16

PHP version history (3 changes)0.0.1PHP ^8.1

1.0.5PHP ^8.2

1.2.0PHP ^8.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7535935?v=4)[Spatie](/maintainers/spatie)[@spatie](https://github.com/spatie)

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (89 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (20 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (14 commits)")[![stfndamjanovic](https://avatars.githubusercontent.com/u/22433990?v=4)](https://github.com/stfndamjanovic "stfndamjanovic (7 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (5 commits)")[![Nielsvanpach](https://avatars.githubusercontent.com/u/10651054?v=4)](https://github.com/Nielsvanpach "Nielsvanpach (5 commits)")[![riasvdv](https://avatars.githubusercontent.com/u/3626559?v=4)](https://github.com/riasvdv "riasvdv (3 commits)")[![AlexVanderbist](https://avatars.githubusercontent.com/u/6287961?v=4)](https://github.com/AlexVanderbist "AlexVanderbist (2 commits)")[![santos-sabanari](https://avatars.githubusercontent.com/u/3425254?v=4)](https://github.com/santos-sabanari "santos-sabanari (1 commits)")[![manadinho](https://avatars.githubusercontent.com/u/18038023?v=4)](https://github.com/manadinho "manadinho (1 commits)")

---

Tags

deletioneloquentlaravelphpspatielaravellaravel-deleted-models

###  Code Quality

TestsPest

### Embed Badge

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

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

###  Alternatives

[spatie/laravel-backup

A Laravel package to backup your application

6.0k21.8M191](/packages/spatie-laravel-backup)[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)[wnx/laravel-backup-restore

A package to restore database backups made with spatie/laravel-backup.

203330.1k2](/packages/wnx-laravel-backup-restore)

PHPackages © 2026

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