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

Doctrine Orm Bridge Laravel Package

dlakomski/doctrine-orm-bridge

Doctrine ORM bridge for SimpleBus/MessageBus. Provides command bus middlewares to wrap command handling in database transactions and to dispatch domain events generated by Doctrine entities. Links to main SimpleBus repo for issues and PRs.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require simplebus/doctrine-orm-bridge
    
  2. Register Middleware Integrate the bridge into your Laravel AppServiceProvider or a dedicated CommandBusServiceProvider:

    use SimpleBus\MessageBus\MessageBus;
    use SimpleBus\DoctrineORMBridge\Middleware\TransactionMiddleware;
    use Doctrine\ORM\EntityManagerInterface;
    
    public function register()
    {
        $this->app->singleton(MessageBus::class, function ($app) {
            $entityManager = $app->make(EntityManagerInterface::class);
            $bus = new MessageBus([
                new TransactionMiddleware($entityManager),
                // Other middleware...
            ]);
            return $bus;
        });
    }
    
  3. First Use Case: Transactional Commands Define a command handler that leverages Doctrine transactions:

    use SimpleBus\MessageBus\Message\MessageHandlerInterface;
    use Doctrine\ORM\EntityManagerInterface;
    
    class CreateUserCommandHandler implements MessageHandlerInterface
    {
        private $entityManager;
    
        public function __construct(EntityManagerInterface $entityManager)
        {
            $this->entityManager = $entityManager;
        }
    
        public function handle(CreateUserCommand $command)
        {
            $user = new User();
            $user->setName($command->getName());
            $this->entityManager->persist($user);
            $this->entityManager->flush(); // Transaction auto-commits via middleware
        }
    }
    

Implementation Patterns

Workflow: Command Handling with Transactions

  1. Middleware Stack Place TransactionMiddleware first in your middleware stack to ensure transactions wrap the entire command handling:

    $bus = new MessageBus([
        new TransactionMiddleware($entityManager),
        new LoggingMiddleware(),
        // Other middleware...
    ]);
    
  2. Domain Events Integration Use DomainEventMiddleware to publish events after command execution:

    use SimpleBus\DoctrineORMBridge\Middleware\DomainEventMiddleware;
    
    $bus = new MessageBus([
        new TransactionMiddleware($entityManager),
        new DomainEventMiddleware($entityManager),
    ]);
    
  3. Laravel-Specific Integration Bind the bridge to Laravel’s container in config/services.php:

    'doctrine_orm_bridge' => [
        'transaction_middleware' => SimpleBus\DoctrineORMBridge\Middleware\TransactionMiddleware::class,
        'domain_event_middleware' => SimpleBus\DoctrineORMBridge\Middleware\DomainEventMiddleware::class,
    ],
    
  4. Event Listeners Attach listeners to Doctrine events (e.g., postPersist) to trigger commands:

    $entityManager->getEventManager()->addEventListener(
        'postPersist',
        new CommandTriggerListener($commandBus, UserCreatedCommand::class)
    );
    

Gotchas and Tips

Pitfalls

  1. EntityManager State

    • After a failed transaction, the EntityManager closes. The bridge automatically resets it via ManagerRegistry, but ensure your container rebinds it if needed.
    • Fix: Verify EntityManager is singleton-scoped in Laravel’s container.
  2. Event Replay

    • Events are erased after processing (since v2.0.1). If you need replayability, store events in a separate table.
  3. Middleware Order

    • Place TransactionMiddleware before DomainEventMiddleware to ensure events are flushed within the same transaction.

Debugging

  • Transaction Rollbacks Use Laravel’s DB::transaction() as a sanity check:

    DB::transaction(function () use ($bus, $command) {
        $bus->dispatch($command);
    });
    
  • Event Dispatching Log events before/after DomainEventMiddleware:

    $bus = new MessageBus([
        new LoggingMiddleware(), // Log before events
        new DomainEventMiddleware($entityManager),
        new LoggingMiddleware(), // Log after events
    ]);
    

Extension Points

  1. Custom Transaction Handling Extend TransactionMiddleware to add pre/post-transaction logic:

    class CustomTransactionMiddleware extends TransactionMiddleware
    {
        public function handle($message, callable $next)
        {
            $this->logTransactionStart();
            $result = parent::handle($message, $next);
            $this->logTransactionEnd();
            return $result;
        }
    }
    
  2. Event Filtering Override DomainEventMiddleware to filter events:

    class FilteredDomainEventMiddleware extends DomainEventMiddleware
    {
        protected function shouldProcessEvent($event)
        {
            return $event instanceof CriticalEvent;
        }
    }
    
  3. Laravel Queue Integration Dispatch commands to queues while preserving transactions:

    $bus->dispatch(new CreateUserCommand());
    // Queue the command via Laravel's queue system
    

Config Quirks

  • Doctrine Version Compatibility Ensure your Doctrine ORM version matches the bridge’s requirements (check composer.json).

    • Fix: Use doctrine/orm:^2.7 for Laravel 8+ compatibility.
  • EntityManager Binding Laravel’s EntityManager must be bound as a singleton:

    $this->app->singleton(EntityManagerInterface::class, function ($app) {
        return $app->make('doctrine.entitymanager.entity_manager');
    });
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours