Your Guide to Laravel Excellence

Better Error Handling with onFailure Callback in Laravel's DB::transaction() (New in Laravel 12.9)

Better Error Handling with onFailure Callback in Laravel's DB::transaction() (New in Laravel 12.9)

In Laravel 12.9, the DB::transaction() method was improved to allow an onFailureCallback, which is a function that gets called if the transaction fails (throws an exception or error).

Before this update:

If something failed during a DB::transaction(), you could catch it outside manually, but it wasn't built-in cleanly.

Now:

  • Laravel lets you pass a second parameter, onFailureCallback, inside the DB::transaction() itself.

  • This makes handling failures more elegant and localized.

  • It keeps your code cleaner and centralized around the transaction logic.

DB::transaction(
    function () use ($id) {
        $articleImage = ArticleImages::findOrFail($id);
        $articleImage->delete();
    },
    onFailureCallback: function (Throwable $e) use ($user, $id) {
        $articleImage = ArticleImages::find($id); // It might have been deleted or not
        Notification::send($user, new ImageDeletionFailedNotification($articleImage, $e->getMessage()));
    }
);

✅ **Main Transaction: Try to find and delete an image.

If it fails:

Maybe image is already deleted, or some DB error happens.

The onFailureCallback sends a notification to the user telling them the deletion failed, along with the error message.

Real Life Examples:

  1. Order Processing System

Suppose you are processing an e-commerce order:

DB::transaction(
    function () use ($order) {
        $order->markAsPaid();
        $order->reduceStockLevels();
    },
    onFailureCallback: function (Throwable $e) use ($user, $order) {
        Notification::send($user, new OrderProcessingFailedNotification($order, $e->getMessage()));
    }
);

If marking as paid or reducing stock fails, the customer is notified that the order couldn't be processed.

  1. Blog Publishing Workflow

If either saving post or notifying subscribers fails, the error is logged for investigation.

DB::transaction(
    function () use ($postData) {
        $post = Post::create($postData);
        Notification::send(User::subscribers(), new NewPostNotification($post));
    },
    onFailureCallback: function (Throwable $e) {
        Log::error('Blog publishing failed: '.$e->getMessage());
    }
);

Publishing a blog creates the blog post and notifies all subscribers:

Recommeded Posts

How to Use Laravel Service Container and Dependency Injection Easily

How to Use Laravel Service Container and Dependency Injection Easily

Learn what Laravel's Service Container and Dependency Injection are, and how they help you build better and faster PHP apps in 2025.

2 months ago Read article →
Real-Time Chat App with Laravel Websockets

Real-Time Chat App with Laravel Websockets

Learn how to build a real-time messaging system in this comprehensive tutorial. Explore sending messages via WebSockets, broadcasting events, receiving messages with Pusher, displaying user status (online/offline), and showcasing old message histories smoothly

2 months ago Read article →
How to Handle Job Failures in Laravel 12 with FailOnException

How to Handle Job Failures in Laravel 12 with FailOnException

Learn how to handle job failures in Laravel 12 using the new FailOnException trait. Clean up your job classes, avoid repetitive boilerplate, and follow Laravel best practices with this simple guide.

2 weeks ago Read article →
How to Add Real-Time Comments in Laravel 11 with Laravel Reverb

How to Add Real-Time Comments in Laravel 11 with Laravel Reverb

How to Add Real-Time Comments in Laravel 11 with Laravel Reverb

2 months ago Read article →