Skip to main content

Database Transaction Helper

RunDbTransaction

RunDbTransaction is a fluent helper for running safe and clean database transactions in Laravel.
It handles edge cases around rollback levels, especially when using custom exceptions like DefaultException (common in our codebase).

⚠️ Why This Matters

When a DefaultException is thrown (one that already performs a rollback), using DB::beginTransaction() with a try-catch around it can lead to double rollback errors or broken transaction levels.

That's the main problem RunDbTransaction solves:

  • It detects if rollback has already happened (e.g. inside DefaultException)

  • Prevents Laravel’s transaction level from going out of sync

  • Lets you catch and handle exceptions cleanly — even continue without rollback if needed

It also works great with regular exceptions that don’t trigger rollback on their own.


✅ Basic Usage

$successful = RunDbTransaction::create()
    ->transaction(fn() => $this->mainTransaction())
    ->run();
  • Always call run() at the end.

  • Returns true if transaction was committed.

  • Returns false if it was rolled back.


⚙️ Methods

transaction(callable $callback)

Defines the main code block that runs inside the transaction.

->transaction(fn() => $this->doSomething())

intercept(callable $handler)

Optional. Runs only if an exception was thrown and rollback hasn’t yet happened.

This is where you can handle something like DefaultException, and still choose to commit the transaction.

->intercept(fn($e) => $this->handleBeforeRollback($e))
  • Return truthy value → Commit happens

  • Return falsy value → Rollback proceeds


catch(callable $handler)

Optional. Runs after rollback. Even if intercept ran but returned false.

->catch(fn($e) => $this->handleAfterRollback($e))

🧪 Force Rollback Manually

If you want to rollback without throwing (e.g. for simulation/test):

php
RunDbTransaction::runTransaction(function () { $this->doSomething(); return RunDbTransaction::DO_ROLLBACK; });
  • Returns false

  • No exception handlers are triggered

  • Transaction is rolled back cleanly


🔁 Shortcuts

RunDbTransaction::runTransaction(fn() => ...)

Basic one-liner with safe rollback handling:

php
$ok = RunDbTransaction::runTransaction(fn() => $this->doSomething());

RunDbTransaction::runOrFail(fn() => ...)

Same as above, but rethrows the exception if one happens. When you only need managed transaction block:

php
RunDbTransaction::runOrFail(fn() => $this->doSomething());

Also works with DO_ROLLBACK – in that case it rolls back without throwing.


💡 Summary Table

MethodDescription
transaction()Required. Code block to wrap in a transaction
intercept()Optional. Runs if exception is thrown before rollback
catch()Optional. Runs after rollback, always gets the exception
run()Executes the transaction logic
runTransaction()Shorthand with rollback detection
runOrFail()Shorthand that rethrows exception
DO_ROLLBACKSpecial return value to force rollback without exception