aeatech/transaction-manager-doctrine-adapter
Installation Add the package via Composer:
composer require aeatech/transaction-manager-doctrine-adapter
Ensure aeatech/transaction-manager is also installed (this adapter depends on it).
Register the Adapter
In your Laravel service provider (e.g., AppServiceProvider), bind the Doctrine DBAL adapter to the transaction manager:
use AEATech\TransactionManager\TransactionManager;
use AEATech\TransactionManagerDoctrineAdapter\DoctrineAdapter;
public function register()
{
$this->app->singleton(TransactionManager::class, function ($app) {
$dbalConnection = Doctrine\DBAL\DriverManager::getConnection([
'url' => 'mysql://user:pass@localhost/db',
]);
return new TransactionManager(new DoctrineAdapter($dbalConnection));
});
}
First Use Case: Wrapping a Transaction Use the transaction manager to execute a block of code within a transaction:
use AEATech\TransactionManager\TransactionManager;
public function updateInventory(TransactionManager $transactionManager)
{
$transactionManager->transactional(function () {
// Execute DBAL queries here (e.g., via Doctrine DBAL)
$connection->executeStatement('UPDATE inventory SET stock = stock - 1 WHERE id = ?', [1]);
});
}
Basic Transaction
Use transactional() for simple rollback-on-failure logic:
$transactionManager->transactional(function () {
$this->repository->deductStock($productId);
$this->repository->logTransaction($userId, $productId);
});
Nested Transactions (Best-Effort) The adapter supports nested transactions via Doctrine DBAL’s savepoints:
$transactionManager->transactional(function () {
$this->repository->updateOrderStatus($orderId, 'processing');
$transactionManager->transactional(function () {
$this->repository->notifyCustomer($orderId);
// If this fails, only the nested block rolls back.
});
});
Explicit Rollback Manually trigger a rollback if needed:
try {
$transactionManager->transactional(function () {
// ...
});
} catch (\Exception $e) {
$transactionManager->rollback();
throw $e;
}
Laravel Query Builder Compatibility If using Laravel’s Query Builder alongside Doctrine DBAL, ensure both share the same connection:
$connection = DB::connection('doctrine_dbal');
$transactionManager = new TransactionManager(new DoctrineAdapter($connection));
Parameter Binding Explicitly bind parameters to avoid SQL injection and leverage prepared statements:
$connection->executeStatement(
'INSERT INTO logs (user_id, action) VALUES (?, ?)',
[$userId, 'purchase']
);
Doctrine ORM Integration For projects using Doctrine ORM, wrap ORM operations in the transaction manager:
$transactionManager->transactional(function () use ($entityManager) {
$entityManager->persist($entity);
$entityManager->flush();
});
Connection Leaks Ensure the Doctrine DBAL connection is properly closed after use, especially in long-running scripts:
$connection->close();
Nested Transaction Limitations Doctrine DBAL’s savepoints (used for nested transactions) may not be supported by all databases. Test thoroughly with your DBMS.
Transaction Timeout
Long-running transactions may hit database timeouts. Use setTransactionIsolation() or database-specific configurations to adjust:
$connection->beginTransaction();
$connection->setTransactionIsolation(\Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED);
Parameter Binding Quirks
Some databases (e.g., SQLite) may not support named parameters. Stick to ? placeholders for cross-DB compatibility.
Enable Logging Configure Doctrine DBAL logging to debug transaction issues:
$connection->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
Check Transaction Status Verify transaction state before committing:
if (!$connection->isTransactionActive()) {
throw new \RuntimeException('Transaction not active');
}
Custom Isolation Levels Override the default isolation level in the adapter:
$adapter = new DoctrineAdapter($connection, \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE);
Event Listeners Attach listeners to the transaction manager for pre/post-commit hooks:
$transactionManager->addListener('commit', function () {
Log::info('Transaction committed');
});
Fallback for Unsupported Features Implement a fallback mechanism for databases lacking savepoints:
if (!$connection->supportsSavepoints()) {
// Fallback to manual rollback logic
}
How can I help you explore Laravel packages today?