DoctrineORMBridge¶
This package provides command bus middlewares that can be used to integrate SimpleBus/MessageBus with Doctrine ORM.
It provides an easy way to wrap command handling in a database transaction and handle domain events generated by entities.
@TODO The intro should explain what it does.
Getting started¶
Preparations¶
To use the middlewares provided by the library, set up a command bus and an event bus, if you didn’t already do this:
1 2 3 4 5 6 7 | use SimpleBus\Message\Bus\Middleware\MessageBusSupportingMiddleware;
$commandBus = new MessageBusSupportingMiddleware();
...
$eventBus = new MessageBusSupportingMiddleware();
...
|
Make sure to also properly set up an entity manager:
1 2 | // $entityManager is an instance of Doctrine\ORM\EntityManager
$entityManager = ...;
|
Now add the available middlewares for transaction handling and domain events.
Transactions¶
It is generally a good idea to wrap command handling in a database
transaction. If you want to do this, add the
WrapsMessageHandlingInTransaction
middleware to the command bus.
Provide an instance of the Doctrine ManagerRegistry
interface and
the name of the entity manager that you want to use.
1 2 3 4 5 6 7 8 9 10 11 12 | use SimpleBus\DoctrineORMBridge\MessageBus\WrapsMessageHandlingInTransaction;
/*
* $managerRegistry is an instance of Doctrine\Common\Persistence\ManagerRegistry
*
* For example: if you use Symfony, use the "doctrine" service
*/
$managerRegistry = ...;
$transactionalMiddleware = new WrapsMessageHandlingInTransaction($managerRegistry, 'default');
$commandBus->addMiddleware($transactionalMiddleware);
|
Note
Once you have added this middleware, you shouldn’t call
EntityManager::flush()
manually from inside your command
handlers anymore.
Domain events¶
Using the message recorder
facilities
from SimpleBus/MessageBus
you can let Doctrine ORM collect domain
events and subsequently let the event bus handle them.
Make sure that your entities implement the ContainsRecordedMessages
interface. Use the PrivateMessageRecorderCapabilities
trait to
conveniently record events from inside the entity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | use SimpleBus\Message\Recorder\ContainsRecordedMessages;
use SimpleBus\Message\Recorder\PrivateMessageRecorderCapabilities;
class YourEntity implements ContainsRecordedMessages
{
use PrivateMessageRecorderCapabilities;
public function changeSomething()
{
// record new events like this:
$this->record(new SomethingChanged());
}
}
|
Then set up the event recorder for Doctrine entities:
1 2 3 4 5 | use SimpleBus\DoctrineORMBridge\EventListener\CollectsEventsFromEntities;
$eventRecorder = new CollectsEventsFromEntities();
$entityManager->getConnection()->getEventManager()->addEventSubscriber($eventRecorder);
|
The event recorder will loop over all the entities that were involved in the last database transaction and collect their internally recorded events.
After a database transaction was completed successfully these events should be handled by the event bus. This is done by a specialized middleware, which should be appended to the command bus before the middleware that is responsible for handling the transaction.
1 2 3 4 5 6 7 8 9 10 | use SimpleBus\DoctrineORMBridge\MessageBus\WrapsMessageHandlingInTransaction;
use SimpleBus\Message\Bus\MessageBus;
$eventDispatchingMiddleware = new HandlesRecordedMessagesMiddleware($eventProvider, $eventBus);
// N.B. append this middleware *before* the WrapsMessageHandlingInTransaction middleware
$commandBus->appendMiddleware($eventDispatchingMiddleware);
$transactionalMiddleware = new WrapsMessageHandlingInTransaction($entityManager);
$commandBus->appendMiddleware($transactionalMiddleware);
|
Note
The MessageBusSupportingMiddleware
class also has a
prependMiddleware()
method, which you can use to prepend
middleware instead of appending it.