The League of Extraordinary Packages

Our Packages:

Presented by The League of Extraordinary Packages

Getting Started

Plugins

Doctrine

Author Source Packagist

This package provides a TransactionMiddleware and a RollbackOnlyTransactionMiddleware. Both middleware execute each command in a separate Doctrine ORM transaction.

The TransactionMiddleware will start a transaction before each command begins. If the command is successful, it will flush and commit the EntityManager (saving you keystrokes). If an exception is raised, TransactionMiddleware rolls back the transaction, closes the EntityManager and rethrows the exception (saving you from corrupt data).

RollbackOnlyTransactionMiddleware does the same thing, but only rolls back the transaction: it does not close the entity manager.

Setup is simple:

use League\Tactician\CommandBus;
use League\Tactician\Doctrine\ORM\TransactionMiddleware;

$commandBus = new CommandBus(
    [
        new TransactionMiddleware($entityManager),
        // other middleware...
    ]
);

Transactions and Subcommands

Sometimes, you might have a Command that fires off more commands, usually via events. The question then becomes, should these subcommands run inside the same transaction as the command that originally fired them?

The recommended approach is having each command run in a separate transaction. This keeps transaction boundaries smaller and makes commands easy to reason about because they only rely on themselves.

You can configure this by using the LockingMiddleware shipped in the core Tactician package. By placing the LockingMiddleware above the TransactionMiddleware, you can ensure that each Command executes separately. For more details, see the LockingMiddleware documentation.

Still, Tactician is flexible and you can choose to run all subcommands inside the same transaction if you want. Just place the TransactionMiddleware above the LockingMiddleware or leave the LockingMiddleware off entirely. Again, we don’t recommend this but it is possible.