Laravel Eloquent: How to Cascade Delete Related Models

Updated: January 17, 2024 By: Guest Contributor Post a comment

Introduction

Laravel Eloquent provides an active record implementation that allows developers to work with database objects in a more intuitive way. Deleting records along with their related models is an important aspect of handling database relationships. In this tutorial, we will explore how to implement cascade deletes using Laravel Eloquent so that when a parent model is removed, its related models are automatically deleted.

Understanding Relationship Types

Before diving into cascade deletes, it’s essential to know the different types of relationships Eloquent supports, such as one-to-one, one-to-many, and many-to-many. Each has its own way of handling related data on deletion.

Setting Up Cascade Deletes

To automatically delete related models in Laravel Eloquent, you need to define the onDelete(‘cascade’) method in your migrations for foreign keys. Below is how to set this up:

Schema::table('posts', function (Blueprint $table) {
    $table->foreign('user_id')
        ->references('id')->on('users')
        ->onDelete('cascade');
});

Implementing this in your migrations will ensure that when a User is deleted, all the associated Posts are automatically removed from the database.

Cascade Delete in Eloquent Relationships

In cases where you can’t modify migrations, or you need to perform more complex deletion procedures, you might opt to define a delete method within your model. Here, you can handle the deletion of related models manually.

class User extends Authenticatable
{
    public function delete()
    {
        DB::transaction(function() {
            $this->posts()->delete();
            parent::delete(); // Finally, delete the user
        });
    }
}

This code overrides the delete method on the User model to first delete all associated Post models inside a database transaction. It ensures that if an error occurs, the operation is rolled back, maintaining the integrity of your data.

Dealing with Soft Deletes

Soft deleting is a feature in Laravel that marks a record as ‘deleted’ without actually removing it from the database. This can sometimes complicate cascade deletion, as simply deleting a parent model won’t affect soft-deleted related models. You will have to tweak your deletion logic to account for this.

class User extends Authenticatable
{
    use SoftDeletes;

    public function delete()
    {
        $this->posts()->forceDelete(); // Force delete all related posts
        parent::delete();
    }
}

Advanced Cascade Deletion Scenarios

What if you have more complex relationships, like a many-to-many relationship? Or what if you have a requirement to perform some action on each related model before it gets deleted? You could use model observers.

class UserObserver
{
    public function deleting(User $user)
    {
        $user->posts()->each(function($post) {
            // Perform action before deletion
            $post->delete(); // Then delete the post
        });
    }
}

With observers, you tap into Eloquent’s model events to handle related deletions. It’s a clean way to encapsulate this functionality without cluttering your model.

Test Your Cascade Deletes

Before pushing your app to production, ensure you’ve written tests that verify your cascade deletes work as expected. These tests could be feature tests that check the database state after a deletion occurs.

Conclusion

In this tutorial, we walked through several methods of implementing cascade deletes in Laravel Eloquent. From modifying migrations to utilizing Eloquent Observers, we covered the basics to more advanced concepts, ensuring a safe and practical approach to managing database relations.