Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel eloquent static boot deleting multiple relationship

I have this model that uses a static boot for deleting related models/tables in the db. First is the product model.

 protected static function boot() {
    parent::boot();

    static::deleting(function($product) {
        $product->hearts()->delete();
        $product->comments()->delete();
    });
}

It deletes the hearts and comments and it's working like a charm. But the problem is I have this reply model that has an relationship with my comment model and that reply model is being referenced from the comment model

public function replies()
{
    return $this->hasMany("App\Reply");
}

Then in my comment model I used another static boot for "Chaining" the boot delete from the product

 protected static function boot() {
    parent::boot();

    static::deleting(function($comment) { 
        $comment->replies()->delete();
    });
}

but it's not working. Can you guys give me an insight why this isn't working? Logically it should work because the comment is being deleted. Thank you.

like image 903
Keannu Alforque Atilano Avatar asked Mar 13 '17 13:03

Keannu Alforque Atilano


2 Answers

Inside your first deleting event, you are calling $product->comments()->delete();. This line is actually calling the delete() method on a query builder object, and not the Comment models. Because no Comment models are created during the delete, the deleting event on the Comment will not be executed.

In order do to this type of application level cascading deletes, you will need to make sure that delete is only ever called on Comment instances. You an either loop through the related records and delete them, or get a list of their ids and use the destroy() method (which does a loop behind the scenes):

// do a loop yourself
static::deleting(function($product) {
    foreach ($product->comments as $comment) {
        $comment->delete();
    }
});

// or, destroy all the ids
static::deleting(function($product) {
    $ids = $product->comments()->lists('id')->all();
    Comment::destroy($ids);
});

Having said all that, if you have simple relationships and access to modify the database, you'll probably want to setup database level cascading deletes. This will be much faster than application level cascading deletes, as you won't need to load every model for every record to delete.

However, if you're in a situation where you need application level cascading deletes (e.g. polymorphic relationships, application architect requires them, etc), I do have a package that takes care of this for you: shiftonelabs/laravel-cascade-deletes. You just add a trait to your model and define the array of relationships to cascade delete, and you don't need to worry about anything else.

like image 112
patricus Avatar answered Nov 05 '22 17:11

patricus


This is working for me

static::deleting(function($product) {
   $product->comments->each->delete()
});
like image 40
Sreeraj R Avatar answered Nov 05 '22 17:11

Sreeraj R