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))
🚀 Full Example with All Handlers
$successful = RunDbTransaction::create()
->transaction(fn() => $this->mainTransaction())
->intercept(fn($e) => $this->interceptException($e))
->catch(fn($e) => $this->catchException($e))
->run();
🧪 Force Rollback Manually
IfYou youcan wantforce toa rollback withoutby throwingreturning (e.g.a forspecial simulation/test):flag:
-
Returns
false
-
No exception handlers are triggered
-
Transaction is rolled back cleanly
🔁 Shortcuts
RunDbTransaction::runTransaction(fn() => ...)
Basic one-liner with safe rollback handling: