Laravel SoftDelete Action
View Package
Overview: LaravelSoftDeleteAction is a Laravel package designed to enhance the behavior of models that use the SoftDeletes trait by mimicking database ON DELETE constraints directly in your Eloquent models.
Installation: Install the package via Composer:
composer require dipesh79/laravel-softdelete-action
Usage:
You should have SoftDeletes trait on your model to use this functionality. Use 'HandlesSoftDeleteActions' trait on your model.
<?php namespace App\Models; use Dipesh79\LaravelSoftDeleteAction\Traits\HandlesSoftDeleteActions; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; class Category extends Model { use HandlesSoftDeleteActions, HasFactory, SoftDeletes; protected $guarded = []; /** * @var array|string[] $onDelete */ protected array $onDelete = [ 'posts' => 'cascade', // cascade,setNull,restrict,setDefault ]; public function posts(): HasMany { return $this->hasMany(Post::class); } /** * Get the default foreign key value for the relation. * * @param string $relation * @return int|null */ public function getDefaultForeignKeyValueForRelation(string $relation): ?int // This function is needed if you have setDefault option { if ($relation === 'posts') { return 1; } return null; } }
Example of Post Model
<?php namespace App\Models; use Dipesh79\LaravelSoftDeleteAction\Traits\HandlesSoftDeleteActions; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; class Post extends Model { use HasFactory, SoftDeletes, HandlesSoftDeleteActions; protected $guarded = []; public function category(): BelongsTo { return $this->belongsTo(Category::class, 'category_id'); } public function comments(): HasMany { return $this->hasMany(Comment::class); } protected array $onDelete = [ 'comments' => 'cascade', ]; }
This will also support multi children relation
<?php namespace App\Models; use Database\Factories\CommentFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; class Comment extends Model { /** @use HasFactory<CommentFactory> */ use HasFactory, SoftDeletes; protected $guarded = []; public function post(): BelongsTo { return $this->belongsTo(Post::class, 'post_id'); } }
Core Functionalities:
- Children Cascade Option On Delete
- Children Restore Option On Restore
Note: Make sure that your children model also has SoftDeletes Trait. You can only restore the children entities if you have 'cascade' option on Parent Model.
Exceptions:
- MissingSoftDeletesTraitException
If your model is missing 'SoftDeletes' trait then you will get this exception. Make sure that you have used this trait on your model.
- MissingOnDeletePropertyException
If your model is missing 'onDelete' property then you will get this exception. Make sure that you have added this property on your model.
- InvalidOnDeleteArrayException
If 'onDelete' property is not array then you will get this exception. Make sure that this property has return type of array.
- MissingDefaultForeignKeyValueMethodException
If you have option as 'setDefault' then you will need to have 'getDefaultForeignKeyValueForRelation' method on your model with this structure.
<?php class Category extends Model { use HandlesSoftDeleteActions, HasFactory, SoftDeletes; ....
/** * Get the default foreign key value for the relation. * * @param string $relation * @return int|null */ public function getDefaultForeignKeyValueForRelation(string $relation): ?int { if ($relation === 'posts') { return 1; } return null; } }
- RestrictException
If you have used 'restrict' option defined for your model then you will get this exception. This will prevent you to delete your parent model to be deleted if this relation has child elements.
Make sure to use \Illuminate\Support\Facades\DB::beginTransaction() before try catch block and catch this exception and rollback the transaction and show proper message for users. The default message for this exception is like this. "Cannot delete this instance of model {ModelName} because it is related to instance of model {relatedModelName}".
- InvalidActionOnDeleteException
You will get this exception when you have defined invalid option on 'OnDelete' property. The Valid options are: 'cascade','setNull','setDefault' and 'restrict'.
You can only use this to delete or restore the children elements. This cannot be used to restore or delete parent elements.
Happy Coding Artisans!!