Cascade delete and restore when using the Laravel or Lumen SoftDeletes feature.

Overview

Header

Build Status Codacy Badge Codacy Badge StyleCI Badge

Laravel/Lumen Soft Cascade Delete & Restore

Cascade delete and restore when using the Laravel or Lumen SoftDeletes feature.

Why do I need it?

To make soft deleting and restoring relations easy.

If you enjoy features like MySQL cascade deleting but want to use Laravels SoftDeletes feature you'll need to do some extra steps to ensure your relations are properly deleted or restored.

This package is intended to replace those steps with a simple array that defines the relations you want to cascade.

Installation

Install with composer

composer require askedio/laravel-soft-cascade

From Laravel 5.5 onwards, it's possible to take advantage of auto-discovery of the service provider. For Laravel versions before 5.5, you must register the service provider in your config/app.php

Askedio\SoftCascade\Providers\GenericServiceProvider::class,

Lumen does not support the auto-discovery feature, you should manually add the provider.

Askedio\SoftCascade\Providers\LumenServiceProvider::class,

Usage

In your Model enable the trait and define $softCascade. Example.

use \Askedio\SoftCascade\Traits\SoftCascadeTrait;

protected $softCascade = ['profiles'];

For restricted relation use. Example.

use \Askedio\SoftCascade\Traits\SoftCascadeTrait;

protected $softCascade = ['addresses@restrict'];

$softCascade is an array of your relation names, in the example you'll see we've defined function profiles() for the relation.

Nested relations work by defining $softCascade in the related Model as you can see here.

After you've defined your relations you can simply trigger delete() or restore() on your Model and your relations will have the same task performed.

User::first()->delete();
User::withTrashed()->first()->restore();

It can also be used with query builder in this way because query builder listener is executed after query, we need to use transaction for rollback query on error due to restricted relationships

try {
    DB::beginTransaction(); //Start db transaction for rollback query when error
    User::limit(2)->delete();
	User::withTrashed()->limit(2)->restore();
    DB::commit(); //Commit the query
} catch (\Exception $e) {
    DB::rollBack(); //Rollback the query
    //Optional, if we need to continue execution only rollback transaction and save message on variable
    throw new \Askedio\SoftCascade\Exceptions\SoftCascadeLogicException($e->getMessage()); 
}

Supported Databases

  • MySQL
  • PostgreSQL
  • SQLite
  • SQL Server

Testing

I have written some very basic tests, certainly more needs to be done here. If you find this useful please help by testing other databases or writing better unit tests because I must move on.

Issues & Contributing

I will be using this with MySQL in a new API so any issues I find related to my use will be resolved. If you find an issue with MySQL please report it and I will fix it.

If you are using another database and have issues please contribute by submitting a pull request. I do not have time to test this with other database but assume all would work.

Comments
  • Delete already deleted

    Delete already deleted

    Post -> comments (3). One comment is already deleted. Post::first()->delete(); After call this all 3 comments has deleted_at set in one moment. Is this how it should works? Restoring post cause restore all 3 comments, i think should only 2 comment which was deleted with post.

    enhancement help wanted 
    opened by mgralikowski 15
  • How to include a soft deleted relation in query? [question]

    How to include a soft deleted relation in query? [question]

    Context

    I have an /admin dashboard to control what to hide and what to show for the frontend. My Job model's relationships:

    Job -> belongsTo: Category Job -> belongsTo: Company

    In my admin/jobs/index.blade view I list the jobs with links to $job->company and $job->category, but because I soft deleted a company or category, it gives route error.

    Question

    How do I query for a trashed relationship so I can still see it?

    I'm querying for jobs correctly, but the relationships aren't found, is there a way to include them even if soft deleted?

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\View\View
     */
    public function index() : View
    {
        $jobs = Job::latest()->withTrashed()->paginate(20);
    
        return view('admin.jobs.index')->with(compact('jobs'));
    }
    

    No rush. And thanks for this package, works great!! 😎

    enhancement 
    opened by emotality 10
  • Bad pivot key name used on BelongsToMany relation

    Bad pivot key name used on BelongsToMany relation

    On belongs to many relation, a bad pivot key name is used to find the good relation

    https://github.com/Askedio/laravel5-soft-cascade/blob/d0424664f3f1e0b9a0c823cf1d2cf6bd00884e6d/src/SoftCascade.php#L146

    Changing getQualifiedForeignPivotKeyName with getRelatedPivotKeyName works for me :)

    opened by squiaios 10
  • Already deleted items should not be in the affectedRows when

    Already deleted items should not be in the affectedRows when

    softcascade should not change deleted_at timestamps of already deleted childmodels, becaus this could break unique Indexes on pivot tables. E.g. i had a parent model wich contains n child models at position 0..n. to ensure each position is only user once for every parent i created a unique index over the columns parent.id,position and deleted_at in the pivot table. when deleteing the parent Model softcascade tries to change all of the related childmodels to the same deleted_at timestamp, which will not work with the unique index. As i can't see no use in changing all the timestamp of already deleted items, i made this PR Kind Regards Tom

    opened by tkempf 9
  • Avoid changing updated_at on restore

    Avoid changing updated_at on restore

    First thank you for this great package!

    As far as I can tell, when cascade-restoring a model, the updated_at column is changed which is a problem for my application. Is it a Laravel problem? Is it this package, and if so, is it the intended behaviour? And finally, is there a way to disable this behaviour?

    Thank you in advance!

    question 
    opened by philippejadin 8
  • What if onDelete is restrict instead of cascade?

    What if onDelete is restrict instead of cascade?

    What will happen if I have used onDelete restrict while creating a relationship. Does this softDelete will raise and restrict that record from softdeleting?

    enhancement 
    opened by rohanvakharia 8
  • Add support for Laravel 6

    Add support for Laravel 6

    I know there's already a PR created for this matter, but it needed further changes.

    PHPUnit and Testbench need to be updated as well. Also, str_ and array_ helpers were removed from the core so the tests failed with a L6 installation.

    opened by Lloople 7
  • Deleting wrong relationship record

    Deleting wrong relationship record

    In my system a Student is a User. After the following code a user was actually deleted. However, it took the students id and used it on the user table, thus, deleting the wrong user.

    This is my controller's method

    try {
                DB::transaction(function () use ($id) {
                    Student::findOrFail($id)->delete();
                }, 5);
                return redirect()->action('StudentController@index');
            } catch (ModelNotFoundException $exception) {
                return redirect()->action('StudentController@index');
            }
    

    This is my Student class

    <?php
    
    namespace App;
    
    use Askedio\SoftCascade\Traits\SoftCascadeTrait;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;
    
    class Student extends Model
    {
        use SoftCascadeTrait;
        use SoftDeletes;
        protected $softCascade = ['user'];
        protected $dates = ['deleted_at'];
        public function user()
        {
            return $this->belongsTo('App\User');
        }
    }
    
    

    Am I missing anything?

    opened by cacpmw 7
  • Model events not fired during cascade

    Model events not fired during cascade

    • Laravel Soft Cacade Version: 5.5.15
    • PHP Version: 7.1
    • Database Driver & Version: MySQL Ver 14.14 Distrib 5.7.16 for osx10.11

    Description

    The model events (like deleting or deleted) are not fired during the soft cascade (not sure if this is intended behavior).

    I want to use Observers to act on the models before they are soft deleted, but they don't get called since the events are not fired.

    I am taking steps to upgrade my Laravel version, so if this is already solved (in case it isn't expected behavior) in the package's 5.6 and 5.7, that would be a relief.

    Thanks for your time. Awesome package, by the way!

    Steps to Reproduce

    Create an Observer for a model that is going to be cascade (soft) deleted and then (soft) delete the parent model.

    Edit: typo.

    Code Example

    ModelA.php

    class ModelA extends Model
    {
         use SoftDeletes;
         use SoftCascadeTrait;
    
         protected $dates = ['deleted_at'];
    
         protected $softCascade = [
             'children'
         ];
    
         public function children()
         {
              return $this->hasMany(ModelB::class);
         }
    }
    

    ModelB.php

    {
         use SoftDeletes;
    
         protected $dates = ['deleted_at'];
    
         public function parent()
         {
              return $this->hasOne(ModelA::class);
         }
    }
    

    ModelBObserver.php

    class ModelBObserver
    {
    
        public function deleting(ModelB $model)
        {
            $model->name = 'Deleted Model';
            $model->save();
        }
    }
    

    In AppServiceProvider.php

    public function boot() 
    {
         ...
         ModelB::observe(ModelBObserver::class);
    }
    

    In a Test file:

    /** @test **/
    public function testEventsOnCascade()
    {
         $modelA = new ModelA();
         $modelA->save();
         $modelA->refresh();
    
         $modelB = new ModelB();
         $modelB->parent_id = $modalA->id;
         $modelB->save();
    
         $modelA->refresh();
         $modelB->refresh();
    
         $modelA->delete();
         $modelB->refresh();
    
         $this->assertEquals('Deleted Model', $modelB->name);
    }
    

    The test fails.

    enhancement 
    opened by felipevfa 7
  • How to skip a relationship when I do a cascade deletion?

    How to skip a relationship when I do a cascade deletion?

    Hi!, I have a "Issuer" model with a one-to-many relationship with "Branch", "Receivers", "Product", if I delete a "Issuer" the related models are correctly deleted in cascade, but, if I delete a "Branch" (which has a one-to-many relationship with "Phone", "Series") "Branch", "Phone", "Series" are deleted because they are dependent on "Branch" and also deletes the "Issuer" model, although "Issuer" and "Branch" have a relationship, how can I avoid that by eliminating a "Branch" the "Issuer" or some other relationship is not deleted?

    opened by aronzillo 7
  • Status of this package

    Status of this package

    On the 15th of February, Laravel 9 support was merged with #131 but no release was ever made. An issue was raised with the request to make a release tag #136 but it has gone un responded.

    Is this package now considered abandoned? 4 months later no release has been created forcing users to either use the main branch which isn't the best or find an alternate package.

    opened by RhysLees 6
  • Laravel 9 support

    Laravel 9 support

    I see a closed topic about Laravel 9 support, but this package is the only one not letting me update to Laravel 9.

    Here's the error:

      Problem 1
        - Root composer.json requires askedio/laravel-soft-cascade ^8.1 -> satisfiable by askedio/laravel-soft-cascade[8.1.0].
        - askedio/laravel-soft-cascade 8.1.0 requires illuminate/support ^7.0|^8.0 -> found illuminate/support[v7.0.0, ..., 7.x-dev, v8.0.0, ..., 8.x-dev] but these were not loaded, likely because it conflicts with another require.
    
    You can also try re-running composer require with an explicit version constraint, e.g. "composer require askedio/laravel-soft-cascade:*" to figure out if any version is installable, or "composer require askedio/laravel-soft-cascade:^2.1" if you know which you need.
    

    Any ideas? Thanks!

    opened by seabasss 4
  • Add

    Add "Set null" behavior

    Add behavior similar to SET NULL action. It will set relation column to NULL when referenced model is deleted.

    For example

    Class User extends Model {
      use SoftDeletes, SoftCascadeTrait;
      
      protected $softCascade = ['phone@setNull'];
      
      public function phone()
      {
        return $this->hasOne(Phone::class);
      }
    }
    
    Class Phone extends Model {
       use SoftDeletes;
      
      public function user()
      {
        return $this->belongsTo(User::class);
      }
    }
    

    Will set NULL in phones.user_id if user was soft deleted.

    opened by rikipm 1
  • Restoring unwanted rows

    Restoring unwanted rows

    Description:

    I have an application where users can create posts. I've given users the ability to delete posts which performs a soft delete on the record. In the following use case i restore records that I don't want.

    • User creates 3 posts
    • User deletes 1 of those posts which is soft deleted
    • Admin deletes the user and it is softdeleted along with 2 more posts(cascading).
    • Admin restores the user, but all 3 posts are restored.

    Is there a way to only restore records that were done by the cascading soft delete.

    opened by dips83 4
  • Deleting Model with lots of relations exhausts memory.

    Deleting Model with lots of relations exhausts memory.

    Doing some testing with the softCascades and I delete a UserType Model with 9 relations. Some of those relations have 2-3 relations themselves, most have none. All relations/models have softDeletes added/enabled.

    When I try deleting the vendor, it eventually dies out with Allocated memory exhausted. Currently its at 4GB, but there has to be a better/more efficient way? Or am wrong in thinking how this should work?

    opened by Xodus-CO 1
  • There is no license information available / No license reference in composer.json

    There is no license information available / No license reference in composer.json

    • Laravel Soft Cascade Version: 7.0.2-8.1.0

    Description:

    BlackDuck software highlights laravel-soft-cascade as library with unknown license. Same is reported by packagist.org ("There is no license information available for the latest version (8.1.0) of this package.")

    Steps To Reproduce:

    Visit packagist repository of the package: https://packagist.org/packages/askedio/laravel-soft-cascade#7.0.2 https://packagist.org/packages/askedio/laravel-soft-cascade

    Solution:

    According to https://getcomposer.org/doc/04-schema.md#license it should be added to composer.json. { "license": "MIT" }

    opened by perstnev 2
Releases(9.0.0)
A laravel package for cascding SoftDeletes delete/restore actions

This is a Laravel 8 package for cascding SoftDeletes delete/restore actions. Laravel 7.0 is supported since v0.1.0 Laravel 8.0 is supported since v0.1

Razi Alsayyed 9 Mar 20, 2022
A laravel package to handle cascade delete and restore on model relations.

Laravel Model Soft Cascade A laravel package to handle cascade delete and restore on model relations. This package not only handle the cascade delete

Touhidur Rahman 18 Apr 29, 2022
A simple laravel package to enable cascade deleting on polymorphic relations.

Morph Cascade Delete A simple laravel package to enable cascade deleting on polymorphic relations. Installation Install with composer composer requi

Moataz Hajres 18 May 15, 2022
A simple blog app where a user can signup , login, like a post , delete a post , edit a post. The app is built using laravel , tailwind css and postgres

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Nahom_zd 1 Mar 6, 2022
An open source Laravel Soundboard with Admin Panel CRUD (Create Read Update Delete) built on Laravel, Bootstrap, and Vue.js

Laravel Soundboard An open source Laravel Soundboard with Admin Panel CRUD (Create Read Update Delete) built on Laravel 5.8, Bootstrap 4, Vue.js, Boot

Jeremy Kenedy 24 Oct 28, 2022
Migrator is a GUI migration manager for Laravel which you can create, manage and delete your migration.

Migrator Migrator is a GUI migration manager for Laravel which you can create, manage and delete your migration. Installation: To install Migrator you

Reza Amini 457 Jan 8, 2023
Perform Bulk/Batch Update/Insert/Delete with laravel.

Bulk Query Perform Bulk/Batch Update/Insert/Delete with laravel. Problem I tried to make bulk update with laravel but i found that Laravel doesn't sup

Mohamed Samir 9 Dec 14, 2021
Laravel soft delete children when parent soft deletes

Laravel Soft Deletes Parent Automatically soft delete a model's children while maintaining their own soft deleted state when you restore the parent mo

Brian Dillingham 55 Dec 18, 2022
Locust are malware that can delete all folders, files, etc. on the system; I

Locust are malware that can delete all folders, files, etc. on the system; It was originally designed for web systems.

Md. Ridwanul Islam Muntakim 21 Dec 9, 2022
Easily interact and control your feature flags from Filament

Easily interact and control your feature flags from Filament

Ryan Chandler 32 Nov 29, 2022
this package can help you to test race condition in Laravel Feature Test

Laravel Async Testing this package can help you to test race condition in Laravel Feature Test Requirements Laravel versions 5.7, 6.x, 7.x and 8.x PHP

Recca Tsai 61 Nov 5, 2022
Feature Switching made easy in Laravel 5

Feature Switching (made easy) for Laravel Need to wrap new features for dev and production? Use a directive in the view or alias in the controller The

Jonathan Bird 24 Dec 1, 2022
An opinionated feature flags package for Laravel

This package provides an opinionated API for implementing feature flags in your Laravel applications. It supports application-wide features as well as model specific feature flags.

Ryan Chandler 157 Nov 24, 2022
A package that adds view-composer like feature to Inertia.js Laravel adapter

Kinetic A package that adds view-composer like feature to Inertia.js Laravel adapter. Use to be able to share props based on the Inertia component nam

Marvin Quezon 76 Dec 12, 2022
Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud Messaging (FCM).

Laravel-FCM Introduction Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud M

Rahul Thapa 2 Oct 16, 2022
Laravel Responder - a package for building API responses, integrating Fractal into Laravel and Lumen

A Laravel Fractal package for building API responses, giving you the power of Fractal with Laravel's elegancy.

Alexander Tømmerås 776 Dec 25, 2022
📦 Adds Laravel Packages Support to Lumen and Vendor Publish Artisan Command.

Laravel Package Support for Lumen: Makes Lumen compatible with Laravel Packages. You can use any Laravel Packages in Lumen by installing Larasupport Package.

Irfaq Syed 127 Dec 17, 2022
A collection of generators for Lumen and Laravel 5.

Lumen generators A collection of generators for Lumen and Laravel 5. Contents Why ? Installation Quick Usage Detailed Usage Model Generator Migration

Amine Ben hammou 349 Mar 24, 2022
CORS (Cross-Origin Resource Sharing) support for Laravel and Lumen

Description This package adds Cross-Origin Resource Sharing (CORS) support to your Laravel application. The package is based on Framework agnostic (PS

null 48 Feb 1, 2020