Weave 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 Messenger Laravel Package

symfony/doctrine-messenger

Doctrine Messenger provides Doctrine integration for Symfony Messenger, letting you store and transport messages using a Doctrine database as the queue backend.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require symfony/doctrine-messenger
    

    Ensure symfony/messenger and doctrine/dbal are also installed (required dependencies).

    Pin to >=5.4.54. The v5.4.54 release is a security release (compare range v5.4.45...v5.4.54). If you're on the 5.4 line, upgrade immediately via composer update symfony/doctrine-messenger. The only other change is a minor fix declaring polyfills required on PHP 7.2 — no API changes, no config changes.

  2. Configure Doctrine Transport Add the transport to your config/packages/messenger.yaml:

    framework:
        messenger:
            transports:
                async: '%env(MESSENGER_TRANSPORT_DSN)%'
            routing:
                'App\Message\YourMessage': async
    

    Define the DSN in .env:

    MESSENGER_TRANSPORT_DSN=doctrine://default
    
  3. Run Migrations Doctrine Messenger creates tables automatically, but run:

    php bin/console doctrine:migrations:diff
    php bin/console doctrine:migrations:migrate
    
  4. Dispatch a Message

    use App\Message\YourMessage;
    use Symfony\Component\Messenger\MessageBusInterface;
    
    public function __construct(private MessageBusInterface $bus) {}
    
    public function sendMessage(): void
    {
        $this->bus->dispatch(new YourMessage('Hello, Doctrine!'));
    }
    
  5. Consume Messages Start the worker:

    php bin/console messenger:consume async -vv
    

First Use Case: Async Email Processing

  1. Create a message class:

    namespace App\Message;
    
    class SendEmailMessage {
        public function __construct(public string $email, public string $subject, public string $body) {}
    }
    
  2. Create a handler:

    namespace App\MessageHandler;
    
    use App\Message\SendEmailMessage;
    use Symfony\Component\Messenger\Attribute\AsMessageHandler;
    
    #[AsMessageHandler]
    class SendEmailHandler {
        public function __invoke(SendEmailMessage $message) {
            // Logic to send email (e.g., using Symfony Mailer)
        }
    }
    
  3. Dispatch from a controller:

    $this->bus->dispatch(new SendEmailMessage(
        '[email protected]',
        'Welcome!',
        'Thanks for signing up!'
    ));
    

Where to Look First

  • Symfony Messenger Documentation (Core concepts).
  • Doctrine Messenger Bridge Docs (Transport-specific details).
  • config/packages/messenger.yaml (Transport and routing configuration).
  • src/Message/ (Your message classes).
  • src/MessageHandler/ (Handler logic).
  • Release changelog (composer show symfony/doctrine-messenger / GitHub compare view) — this bridge ships mostly patch releases; check it after any composer update because security fixes land here first.

Implementation Patterns

Core Workflows

1. Message Dispatching

  • Synchronous: Dispatch messages directly in controllers/services.
    $this->bus->dispatch(new YourMessage());
    
  • Asynchronous: Route to a transport (e.g., async).
    # config/packages/messenger.yaml
    routing:
        'App\Message\YourMessage': async
    

2. Handling Messages

  • Annotate Handlers:
    #[AsMessageHandler]
    class YourHandler {
        public function __invoke(YourMessage $message) {
            // Handle logic
        }
    }
    
  • Middleware: Add processing layers (e.g., logging, validation).
    # config/packages/messenger.yaml
    transports:
        async:
            dsn: doctrine://default
            middleware:
                - 'doctrine_transaction' # Built-in for transactions
                - App\Middleware\YourMiddleware
    

3. Consuming Messages

  • Worker Command:
    php bin/console messenger:consume async --time-limit=300
    
  • Scheduled Consumption (e.g., via cron):
    * * * * * php /path/to/your/project/bin/console messenger:consume async --limit=100
    

4. Retry Logic

  • Automatic Retries: Configure in messenger.yaml:
    transports:
        async:
            dsn: doctrine://default
            retry_strategy:
                max_retries: 3
                delay: 1000
                multiplier: 2
    
  • Failed Messages: Check the messenger_messages history table or use:
    php bin/console messenger:failed:show
    php bin/console messenger:failed:retry
    

Integration Tips

1. Doctrine Transactions

  • Enable transactional handling in messenger.yaml:
    transports:
        async:
            dsn: doctrine://default
            middleware:
                - doctrine_transaction
    
  • Manual Transactions: Use DoctrineTransactionMiddleware in custom middleware.

2. Custom Schema

  • Extend the schema via migrations or events:
    // src/Doctrine/SchemaExtension.php
    namespace App\Doctrine;
    
    use Doctrine\DBAL\Schema\Schema;
    use Symfony\Component\Messenger\Transport\Doctrine\DoctrineTransport;
    
    class SchemaExtension {
        public function __invoke(Schema $schema, DoctrineTransport $transport) {
            $schema->getTable($transport->getTableName())->addColumn('custom_field', 'string');
        }
    }
    
    Register in config/packages/messenger.yaml:
    transports:
        async:
            dsn: doctrine://default
            schema_extension: App\Doctrine\SchemaExtension
    

3. Batching

  • Process messages in batches for efficiency:
    transports:
        async:
            dsn: doctrine://default
            options:
                batch_size: 50
    

4. Prioritization

  • Use multiple transports with routing:
    routing:
        'App\Message\HighPriorityMessage': high_priority
        'App\Message\LowPriorityMessage': low_priority
    transports:
        high_priority:
            dsn: doctrine://default
            options:
                priority: 1
        low_priority:
            dsn: doctrine://default
            options:
                priority: 2
    

5. Testing

  • In-Memory Transport: For unit tests:
    # config/packages/test/messenger.yaml
    transports:
        test:
            dsn: 'doctrine://default'
            options:
                table_name: 'test_messages'
    
  • Mock Handlers: Use MessageBusInterface mocks in PHPUnit:
    $bus = $this->createMock(MessageBusInterface::class);
    $bus->expects($this->once())->method('dispatch');
    

6. Keeping the Bridge Patched

  • Add the bridge to your update routine — it's a low-churn component that mostly receives bugfixes and the occasional security patch:
    composer outdated symfony/doctrine-messenger
    composer update symfony/doctrine-messenger --with-dependencies
    
  • Run your messenger integration tests (dispatch → consume → assert DB state) after upgrading; the transport's failure/retry behaviour is the most likely place for regressions.

Gotchas and Tips

Pitfalls

  1. Security Releases Are Silent

    • Issue: The v5.4.54 bump is flagged only as [SECURITY] Security release in the changelog, with no description of the affected code path. Composer won't warn you beyond the version constraint.
    • Fix: Treat any security tag on this package as a must-update. Pin a minimum ("symfony/doctrine-messenger": ">=5.4.54") and review the advisory/GitHub compare view for the affected transport behaviour.
  2. PHP 7.2 Polyfill Declaration (v5.4.54 minor change)

    • Issue: #65724 declares the polyfills required by the code on PHP 7.2. If you run an old PHP runtime and manage polyfills manually (symfony/polyfill-*), you may see a dependency conflict or a missing-function error after upgrading.
    • Fix: Let Composer resolve polyfills (don't pin symfony/polyfill-* without a reason); if you must, run composer why symfony/polyfill-* after updating.
  3. Schema Conflicts

    • Issue: Doctrine Messenger creates tables (messenger_messages). Conflicts arise if these names clash with existing tables.
    • Fix: Customize table names via the DSN:
      MESSENGER_TRANSPORT_DSN=doctrine://default?table_name=app_messages
      
  4. Transaction Deadlocks

    • Issue: Long-running handlers can cause deadlocks in high-concurrency scenarios.
    • Fix: Use doctrine_transaction middleware sparingly or optimize handler logic. Avoid nested transactions.
  5. PostgreSQL Listener Issues

    • Issue: PostgreSQL transports may fail if UNLISTEN queries are sent unnecessarily (fixed in v8.0.5+).
    • Fix: Update to the latest version or manually manage listeners.
  6. Firebird/Oracle Compatibility

    • Issue: Case-sensitive table names or reserved keywords may cause errors.
    • Fix: Use schema extensions or alias tables:
      transports:
          async:
              dsn: doctrine://default
              options:
                  table_name: "MESSAGES" # Quoted for Firebird
      
  7. Message Size Limits

    • Issue: Large messages (e.g., serialized objects) may exceed database column limits.
    • Fix: Use serialize for complex data or store references to external storage (e.g., S3).

Debugging Tips

  1. Check Failed Messages

    php bin/console messenger:failed:show
    php bin/console messenger:failed:retry [ID]
    
  2. Enable Verbose Logging

    php bin/console messenger:consume async -vv
    

    Or configure in config/packages/monolog.yaml:

    handlers:
        messenger:
            type: stream
            path: "%kernel.logs_dir%/messenger.log"
            level: debug
    
  3. Inspect Database Tables

    -- Check pending messages
    SELECT * FROM messenger_messages;
    
    -- Check failed/retried history (if enabled)
    SELECT * FROM messenger_messages WHERE delivered_at IS NOT NULL ORDER BY delivered_at DESC;
    
  4. Confirm You're Actually Patched

    composer show symfony/doctrine-messenger | grep -i versions
    

    Anything below 5.4.54 on the 5.4 branch is missing the security fix.

  5. Slow Consumption

    • Cause: Inefficient handlers or database locks.
    • Fix: Profile the handler, check for missing indexes on messenger_messages (queue_name, available_at), and reduce batch/poll frequency before scaling workers.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource