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 Bus Message Bundle Laravel Package

draw/doctrine-bus-message-bundle

Symfony bundle that integrates Doctrine with the Messenger/command bus pattern, making it easy to dispatch bus messages from Doctrine entities and listeners. Helps coordinate persistence and message handling with clean separation of concerns.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps for Laravel Developers

  1. Bridge Symfony Messenger to Laravel Since this bundle is Symfony-focused, use Symfony Messenger as a microservice or abstract its logic into a Laravel-compatible layer. Start with a Laravel-native alternative:

    composer require symfony/messenger laravel-horizon
    
  2. First Use Case: Dispatch a Message on Entity Save Replace Doctrine lifecycle events with Laravel’s Model::saved():

    // app/Models/User.php
    use Illuminate\Database\Eloquent\Model;
    use App\Jobs\SendWelcomeEmail;
    
    class User extends Model
    {
        protected static function booted()
        {
            static::saved(function ($user) {
                SendWelcomeEmail::dispatch($user);
            });
        }
    }
    
  3. Key Configuration

    • Queue Driver: Set in .env (e.g., QUEUE_CONNECTION=redis).
    • Job Middleware: Add retries in app/Console/Kernel.php:
      protected function schedule(Schedule $schedule)
      {
          $schedule->job(new SendWelcomeEmail($user))->everyMinute()->withoutOverlapping();
      }
      
  4. Where to Look First

    • Symfony Bundle Docs: GitHub README for event-to-message mapping.
    • Laravel Equivalents: Focus on Illuminate\Database\Eloquent\Model observers and Illuminate\Bus\Queueable.
    • Debugging: Use Queue::fake() in tests to verify message dispatch.

Implementation Patterns

Workflows

  1. Event-Driven Messaging Pattern

    • Doctrine (Symfony): Use @DispatchMessage annotations on entities.
      /**
       * @DispatchMessage(event="postPersist", message="App\Message\UserRegistered")
       */
      class User {}
      
    • Laravel Equivalent: Use model observers or traits:
      class UserObserver {
          public function saved(User $user) {
              dispatch(new UserRegistered($user));
          }
      }
      
  2. Message Handling

    • Symfony: Create a message handler class:
      use Symfony\Component\Messenger\Attribute\AsMessageHandler;
      
      #[AsMessageHandler]
      class UserRegisteredHandler {
          public function __invoke(UserRegistered $message) {
              // Send email, log analytics, etc.
          }
      }
      
    • Laravel: Convert to a queue job:
      class SendWelcomeEmail implements ShouldQueue {
          use Dispatchable, InteractsWithQueue;
      
          public function handle() {
              Mail::to($this->user->email)->send(new WelcomeEmail());
          }
      }
      
  3. Integration with Laravel Services

    • Queue Workers: Run Horizon for monitoring:
      php artisan horizon
      
    • Event Subscribers: Replace Doctrine listeners with Laravel’s EventServiceProvider:
      protected $listen = [
          'eloquent.saved: App\Models\User' => [
              'App\Listeners\LogUserActivity',
          ],
      ];
      

Tips for Daily Use

  • Batch Processing: For high-frequency events (e.g., postUpdate), batch messages to reduce queue load:
    // Use Laravel's chunk() for bulk operations
    User::chunk(100, function ($users) {
        foreach ($users as $user) {
            SendUpdateNotification::dispatch($user);
        }
    });
    
  • Dynamic Message Routing: Use Laravel’s route() helper or Symfony’s Router to dynamically resolve message handlers based on entity type.
  • Testing: Mock queue jobs in Laravel tests:
    public function test_user_creation_dispatches_email()
    {
        Queue::fake();
        User::create(['name' => 'John']);
        Queue::assertPushed(SendWelcomeEmail::class);
    }
    

Gotchas and Tips

Pitfalls

  1. Symfony Dependency Overhead

    • The bundle requires Symfony Messenger, which may conflict with Laravel’s queue system. Mitigation: Use Symfony Messenger as a separate service (e.g., via HTTP transport) or abstract its logic into a Laravel-compatible layer.
  2. Transaction Rollback Scenarios

    • If a Doctrine event triggers a message but the transaction rolls back, the message may still be dispatched. Symfony Solution: Use DoctrineTransport with transactional handlers.
    • Laravel Alternative: Wrap queue dispatches in a transaction:
      DB::transaction(function () {
          $user = User::create([...]);
          SendWelcomeEmail::dispatch($user);
      });
      
  3. Message Serialization Issues

    • Symfony Messenger uses PHP’s serialize() by default, which may not work with Laravel’s queue payloads (expects json or php serialization). Fix: Customize the serializer in Laravel’s queue config:
      'serializers' => [
          'php' => Illuminate\Queue\Serializers\PhpSerializer::class,
      ],
      
  4. Event Ordering

    • Doctrine events fire in a specific order (e.g., prePersistpostPersist). In Laravel, ensure observers/jobs respect this order by using priority queues or event ordering in EventServiceProvider.
  5. Debugging Queue Jobs

    • Symfony’s messenger:consume command won’t work in Laravel. Use:
      php artisan queue:work
      
    • For visibility, integrate Laravel Horizon or Blackfire to profile slow jobs.

Debugging Tips

  • Log Dispatch Events: Add logging in model observers or Symfony event listeners:
    Log::debug('Dispatching message for entity', ['entity' => $entity->id]);
    
  • Queue Monitoring: Use Horizon to track stuck jobs:
    php artisan horizon
    
  • Symfony-Specific Tools: If using the bundle directly, leverage Symfony’s debug tools:
    php bin/console debug:event-dispatcher
    php bin/console messenger:consume async -vv
    

Extension Points

  1. Custom Message Handlers

    • Extend Symfony’s MessageHandlerInterface or Laravel’s ShouldQueue to add business logic:
      class CustomHandler implements ShouldQueue {
          public function handle() {
              // Custom logic
          }
      }
      
  2. Dynamic Event Mapping

    • Use Laravel’s dynamic event listeners or Symfony’s compiled event dispatcher to map events at runtime:
      // Laravel example: Dynamic observer registration
      Event::listen('eloquent.saved:*', function ($model) {
          if ($model instanceof User) {
              SendWelcomeEmail::dispatch($model);
          }
      });
      
  3. Transport Abstraction

    • Replace Symfony Messenger’s transports with Laravel’s queue drivers by implementing a wrapper class:
      class LaravelMessengerTransport implements TransportInterface {
          public function send(Message $message) {
              Queue::push(new ProcessMessageJob($message));
          }
      }
      
  4. Testing Strategies

    • Unit Tests: Mock the queue in Laravel:
      Queue::fake();
      $user = User::create([...]);
      Queue::assertPushed(SendWelcomeEmail::class);
      
    • Integration Tests: Use Queue::flush() to process jobs in tests:
      Queue::flush();
      $this->assertDatabaseHas('notifications', [...]);
      

Configuration Quirks

  • Doctrine Lifecycle Events: Ensure lifecycle_callbacks are enabled in config/packages/doctrine.yaml:
    orm:
        entity_managers:
            default:
                lifecycle_callbacks:
                    prePersist: true
                    # ... other events
    
  • Symfony Messenger Routing: If using the bundle, configure routing in config/packages/messenger.yaml:
    framework:
        messenger:
            transports:
                async: '%env(MESSENGER_TRANSPORT_DSN)%'
            routing:
                'App\Message\UserRegistered': async
    
  • Laravel Queue Config: Align with Symfony’s transport settings (e.g., Redis for async):
    QUEUE_CONNECTION=redis
    REDIS_HOST=127.0.0.1
    
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