Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Transaction Manager Doctrine Adapter Laravel Package

aeatech/transaction-manager-doctrine-adapter

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

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

  2. 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));
        });
    }
    
  3. 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]);
        });
    }
    

Implementation Patterns

Workflow: Transactional Operations

  1. Basic Transaction Use transactional() for simple rollback-on-failure logic:

    $transactionManager->transactional(function () {
        $this->repository->deductStock($productId);
        $this->repository->logTransaction($userId, $productId);
    });
    
  2. 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.
        });
    });
    
  3. Explicit Rollback Manually trigger a rollback if needed:

    try {
        $transactionManager->transactional(function () {
            // ...
        });
    } catch (\Exception $e) {
        $transactionManager->rollback();
        throw $e;
    }
    

Integration Tips

  • 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();
    });
    

Gotchas and Tips

Pitfalls

  1. Connection Leaks Ensure the Doctrine DBAL connection is properly closed after use, especially in long-running scripts:

    $connection->close();
    
  2. Nested Transaction Limitations Doctrine DBAL’s savepoints (used for nested transactions) may not be supported by all databases. Test thoroughly with your DBMS.

  3. 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);
    
  4. Parameter Binding Quirks Some databases (e.g., SQLite) may not support named parameters. Stick to ? placeholders for cross-DB compatibility.

Debugging Tips

  • 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');
    }
    

Extension Points

  1. Custom Isolation Levels Override the default isolation level in the adapter:

    $adapter = new DoctrineAdapter($connection, \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE);
    
  2. Event Listeners Attach listeners to the transaction manager for pre/post-commit hooks:

    $transactionManager->addListener('commit', function () {
        Log::info('Transaction committed');
    });
    
  3. Fallback for Unsupported Features Implement a fallback mechanism for databases lacking savepoints:

    if (!$connection->supportsSavepoints()) {
        // Fallback to manual rollback logic
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor