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 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.

Laravel Localization: How to create a Multilingual Website in Laravel

Laravel Localization: How to create a Multilingual Website in Laravel

Laravel Localization: How to create a Multilingual Website in Laravel

2 months ago Read article →
Resize Images using intervention-image

Resize Images using intervention-image

Resize Images using intervention-image

2 months ago Read article →
Laravel 11 - Custom Query Scopes in Route Model Binding

Laravel 11 - Custom Query Scopes in Route Model Binding

Laravel 11 - Custom Query Scopes in Route Model Binding

2 months ago Read article →