aeatech/transaction-manager-mysql
Installation
composer require aeatech/transaction-manager-mysql
Add the service provider to config/app.php:
'providers' => [
// ...
Aeatech\TransactionManager\TransactionManagerServiceProvider::class,
],
Basic Usage
Inject the TransactionManager facade into your controller/service:
use Aeatech\TransactionManager\Facades\TransactionManager;
public function executeTransaction()
{
TransactionManager::begin();
try {
// Execute queries
DB::table('users')->insert(['name' => 'John']);
DB::table('posts')->insert(['user_id' => 1, 'title' => 'Hello']);
TransactionManager::commit();
} catch (\Exception $e) {
TransactionManager::rollback();
throw $e;
}
}
First Use Case
Replace manual DB::beginTransaction()/commit()/rollback() calls with this package for:
Service Layer Transactions Encapsulate transactions in services:
class OrderService {
public function createOrder(Order $order) {
TransactionManager::begin();
try {
$order->save();
$order->inventory->decrement();
TransactionManager::commit();
} catch (\Exception $e) {
TransactionManager::rollback();
throw new OrderFailedException($e);
}
}
}
Middleware for Global Transactions Use middleware to auto-wrap requests:
class TransactionMiddleware {
public function handle($request, Closure $next) {
TransactionManager::begin();
try {
$response = $next($request);
TransactionManager::commit();
return $response;
} catch (\Exception $e) {
TransactionManager::rollback();
throw $e;
}
}
}
Query Builder Integration Chain with Laravel’s query builder:
TransactionManager::begin();
DB::table('users')
->where('active', 1)
->update(['last_login' => now()]);
TransactionManager::commit();
Nested Transactions (if supported):
TransactionManager::begin();
// Outer transaction
TransactionManager::savepoint('user_update');
try {
DB::table('users')->update(['status' => 'active']);
TransactionManager::release('user_update'); // Commit savepoint
} catch (\Exception $e) {
TransactionManager::rollback('user_update'); // Rollback to savepoint
}
Transaction Retry Logic:
$attempts = 0;
while ($attempts < 3) {
try {
TransactionManager::begin();
// Critical operation
TransactionManager::commit();
break;
} catch (\Exception $e) {
TransactionManager::rollback();
$attempts++;
sleep(1);
}
}
No Explicit Savepoints
Unlike DB::transaction(), this package may not support savepoints. Avoid relying on them unless documented.
Connection Binding Ensure the package uses the same DB connection as your queries:
TransactionManager::connection('mysql_replica')->begin();
Exception Handling
Uncaught exceptions will trigger rollbacks. Use try-catch blocks or middleware to handle failures gracefully.
Long-Running Transactions
MySQL has a transaction_isolation limit (e.g., REPEATABLE READ). Avoid holding locks for >1 hour.
Log Transactions
Wrap calls in Log::debug() to track transaction boundaries:
Log::debug('Transaction started', ['scope' => 'order_creation']);
Check for Deadlocks
MySQL errors like 1213 (Deadlock found) indicate transaction conflicts. Add retry logic or optimize query order.
Custom Rollback Logic
Override the default rollback behavior by binding to the transaction.rollback event:
Event::listen('transaction.rollback', function ($transaction) {
// Custom cleanup (e.g., log failed transaction)
});
Transaction Metadata Attach metadata to transactions for auditing:
TransactionManager::begin(['user_id' => auth()->id(), 'action' => 'update_profile']);
Testing Mock transactions in tests:
$this->partialMock(TransactionManager::class, ['begin', 'commit', 'rollback'])
->shouldReceive('begin')
->once();
How can I help you explore Laravel packages today?