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.
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 rangev5.4.45...v5.4.54). If you're on the 5.4 line, upgrade immediately viacomposer 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.
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
Run Migrations Doctrine Messenger creates tables automatically, but run:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
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!'));
}
Consume Messages Start the worker:
php bin/console messenger:consume async -vv
Create a message class:
namespace App\Message;
class SendEmailMessage {
public function __construct(public string $email, public string $subject, public string $body) {}
}
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)
}
}
Dispatch from a controller:
$this->bus->dispatch(new SendEmailMessage(
'[email protected]',
'Welcome!',
'Thanks for signing up!'
));
config/packages/messenger.yaml (Transport and routing configuration).src/Message/ (Your message classes).src/MessageHandler/ (Handler logic).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.$this->bus->dispatch(new YourMessage());
async).
# config/packages/messenger.yaml
routing:
'App\Message\YourMessage': async
#[AsMessageHandler]
class YourHandler {
public function __invoke(YourMessage $message) {
// Handle logic
}
}
# config/packages/messenger.yaml
transports:
async:
dsn: doctrine://default
middleware:
- 'doctrine_transaction' # Built-in for transactions
- App\Middleware\YourMiddleware
php bin/console messenger:consume async --time-limit=300
* * * * * php /path/to/your/project/bin/console messenger:consume async --limit=100
messenger.yaml:
transports:
async:
dsn: doctrine://default
retry_strategy:
max_retries: 3
delay: 1000
multiplier: 2
messenger_messages history table or use:
php bin/console messenger:failed:show
php bin/console messenger:failed:retry
messenger.yaml:
transports:
async:
dsn: doctrine://default
middleware:
- doctrine_transaction
DoctrineTransactionMiddleware in custom middleware.// 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
transports:
async:
dsn: doctrine://default
options:
batch_size: 50
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
# config/packages/test/messenger.yaml
transports:
test:
dsn: 'doctrine://default'
options:
table_name: 'test_messages'
MessageBusInterface mocks in PHPUnit:
$bus = $this->createMock(MessageBusInterface::class);
$bus->expects($this->once())->method('dispatch');
composer outdated symfony/doctrine-messenger
composer update symfony/doctrine-messenger --with-dependencies
Security Releases Are Silent
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.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.PHP 7.2 Polyfill Declaration (v5.4.54 minor change)
#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.symfony/polyfill-* without a reason); if you must, run composer why symfony/polyfill-* after updating.Schema Conflicts
messenger_messages). Conflicts arise if these names clash with existing tables.MESSENGER_TRANSPORT_DSN=doctrine://default?table_name=app_messages
Transaction Deadlocks
doctrine_transaction middleware sparingly or optimize handler logic. Avoid nested transactions.PostgreSQL Listener Issues
UNLISTEN queries are sent unnecessarily (fixed in v8.0.5+).Firebird/Oracle Compatibility
transports:
async:
dsn: doctrine://default
options:
table_name: "MESSAGES" # Quoted for Firebird
Message Size Limits
serialize for complex data or store references to external storage (e.g., S3).Check Failed Messages
php bin/console messenger:failed:show
php bin/console messenger:failed:retry [ID]
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
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;
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.
Slow Consumption
messenger_messages (queue_name, available_at), and reduce batch/poll frequency before scaling workers.How can I help you explore Laravel packages today?