Implementing Soft Deletes in Laravel for Data Recovery and Auditing
Soft deletes are a powerful feature in Laravel that allow you to "delete" records without actually removing them from your database. This approach is invaluable for maintaining data integrity, enabling easy recovery, and meeting auditing or compliance requirements. Let's explore how to implement and leverage soft deletes effectively in your Laravel applications.
Enabling Soft Deletes
To use soft deletes, first add the deleted_at
column to your table migration:
Schema::table('posts', function (Blueprint $table) {
$table->softDeletes();
});
Then, use the SoftDeletes
trait in your model:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
}
Basic Usage
To soft delete a record:
$post->delete();
To restore a soft-deleted record:
$post->restore();
Querying Soft Deleted Records
Soft deleted records are automatically excluded from query results. To include them:
$posts = Post::withTrashed()->get();
To retrieve only soft deleted records:
$posts = Post::onlyTrashed()->get();
Permanently Deleting Records
To permanently remove a soft deleted record:
$post->forceDelete();
Cascading Soft Deletes
For related models, you might want to cascade soft deletes:
class Post extends Model
{
use SoftDeletes;
protected $cascadeDeletes = ['comments'];
public function comments()
{
return $this->hasMany(Comment::class);
}
}
Implement the cascading logic in your model's boot
method:
protected static function boot()
{
parent::boot();
static::deleting(function($post) {
$post->comments()->delete();
});
static::restoring(function($post) {
$post->comments()->restore();
});
}
Global Scopes
Laravel automatically applies a global scope to exclude soft deleted records. You can remove this scope if needed:
protected static function booted()
{
static::addGlobalScope('withTrashed', function (Builder $builder) {
$builder->withTrashed();
});
}
Soft Deletes with Relationships
When working with relationships, you might want to include or exclude soft deleted records:
// Include soft deleted comments
$post->comments()->withTrashed()->get();
// Get only soft deleted comments
$post->comments()->onlyTrashed()->get();
Checking Deletion Status
To check if a model instance is soft deleted:
if ($post->trashed()) {
// This post has been soft deleted
}
Restoring Related Models
When restoring a parent model, you might want to restore related models as well:
class Post extends Model
{
use SoftDeletes;
public function restore()
{
$this->comments()->restore();
return parent::restore();
}
}
Soft Deletes for Auditing
Soft deletes are excellent for auditing purposes. You can track when a record was "deleted":
$deletedAt = $post->deleted_at;
You can also use this for time-based clean-up of old soft-deleted records:
// Delete posts soft-deleted more than a year ago
Post::onlyTrashed()
->where('deleted_at', '<', now()->subYear())
->forceDelete();
Performance Considerations
While soft deletes are powerful, they can impact query performance, especially on large tables. Consider using indexes on the deleted_at
column:
Schema::table('posts', function (Blueprint $table) {
$table->index('deleted_at');
});
Soft deletes in Laravel provide a robust way to implement data recovery and maintain a complete audit trail of your application's data. By leveraging this feature, you can enhance your application's data integrity, provide undo functionality, and meet various compliance requirements.
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!