Laravel SoftDelete Action

Laravel SoftDelete Action

Latest Stable Version Total Downloads License
View Package

Laravel SoftDelete Action.png 178.85 KB
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:

  1. Children Cascade Option On Delete 
  2. 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!!


This post is licensed under CC BY 4.0 by the author.