Installation Add the bundle via Composer:
composer require coa/messenger-bundle
Register the bundle in config/bundles.php (Symfony 4+):
return [
// ...
Coa\MessengerBundle\CoaMessengerBundle::class => ['all' => true],
];
Basic Configuration
Configure the bundle in config/packages/coa_messenger.yaml:
coa_messenger:
transports:
async: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
'App\Message\YourMessage': async
First Use Case Create a message class:
namespace App\Message;
class YourMessage
{
public function __construct(private string $content) {}
public function getContent(): string { return $this->content; }
}
Dispatch the message in a controller/service:
use Symfony\Component\Messenger\MessageBusInterface;
class YourController
{
public function __construct(private MessageBusInterface $bus) {}
public function handle()
{
$this->bus->dispatch(new YourMessage('Hello async world!'));
}
}
Verify Setup
Check the configured transport (e.g., Doctrine, Redis, or Symfony’s async transport) is running and processing messages.
Message Dispatching
MessageBusInterface to dispatch messages:
$this->bus->dispatch(new YourMessage($data));
Bus::class directly:
$this->bus->dispatch(new YourMessage($data)); // Sync by default in tests
Message Handling
@AsMessageHandler:
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler]
class YourMessageHandler
{
public function __invoke(YourMessage $message)
{
// Process $message->getContent()
}
}
#[AsMessageHandler]
class YourMessageHandler
{
public function __construct(private LoggerInterface $logger) {}
public function __invoke(YourMessage $message)
{
$this->logger->info('Processing:', ['content' => $message->getContent()]);
}
}
Transport-Specific Patterns
transports:
doctrine: 'doctrine://default'
transports:
redis: 'redis://localhost'
transports:
sync: 'sync://'
Middleware Integration
# config/packages/messenger.yaml
framework:
messenger:
buses:
messenger.bus.default:
middleware:
- 'Coa\MessengerBundle\Middleware\YourMiddleware'
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;
class YourMiddleware implements MiddlewareInterface
{
public function handle($message, StackInterface $next)
{
// Pre-processing
$result = $next($message);
// Post-processing
return $result;
}
}
Retry Logic
messenger.yaml:
transports:
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
retry_strategy:
max_retries: 3
delay: 1000
Laravel-Specific Adaptations
Bus facade for dispatching (if using Symfony Messenger as a drop-in):
use Illuminate\Bus\Dispatcher;
$dispatcher = app(Dispatcher::class);
$dispatcher->dispatch(new YourMessage('Hello Laravel!'));
queue:work:
php artisan queue:work --queue=coa_messenger
Event-Driven Architecture
// In an event listener
$this->bus->dispatch(new ProcessUserEvent($user));
Testing
Envelope for testing message flow:
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
$envelope = new Envelope(new YourMessage('test'));
$this->bus->dispatch($envelope);
$bus = $this->createMock(MessageBusInterface::class);
$bus->expects($this->once())->method('dispatch');
Transport Configuration
doctrine://default or redis://localhost).MESSENGER_TRANSPORT_DSN is set in .env and matches the bundle’s expectations.php bin/console messenger:consume async -vv for connection errors.Handler Registration
@AsMessageHandler or not tagged as services.services.yaml:
services:
App\MessageHandler\YourMessageHandler:
tags: ['messenger.message_handler']
Message Serialization
#[AsMessage] attribute or implement Serializable:
use Symfony\Component\Messenger\Attribute\AsMessage;
#[AsMessage]
class YourMessage implements Serializable
{
// ...
}
Middleware Order
messenger.yaml:
middleware:
- 'Coa\MessengerBundle\Middleware\Validate'
- 'Coa\MessengerBundle\Middleware\Log'
Laravel Queue Conflicts
jobs).Consume Messages Manually Run the consumer to inspect messages:
php bin/console messenger:consume async --time-limit=3600
Check Failed Messages List failed messages:
php bin/console messenger:failed:list
Retry a failed message:
php bin/console messenger:failed:retry <message-id>
Log Middleware Execution Add debug logging to middleware:
use Psr\Log\LoggerInterface;
class DebugMiddleware implements MiddlewareInterface
{
public function __construct(private LoggerInterface $logger) {}
public function handle($message, StackInterface $next)
{
$this->logger->debug('Handling message:', ['class' => get_class($message)]);
return $next($message);
}
}
Environment-Specific Config Override transport settings per environment:
# config/packages/coa_messenger/dev.yaml
coa_messenger:
transports:
async: 'sync://' # Use sync in dev
Custom Transports
Extend Coa\MessengerBundle\Transport\AbstractTransport to create new transports (e.g., for Kafka or RabbitMQ).
Dynamic Routing
Use a RouterInterface to dynamically route messages:
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
use Symfony\Component\Messenger\Transport\TransportInterface;
class DynamicRouter implements RouterInterface
{
public function getRoute(Envelope $envelope): ?TransportInterface
{
if ($envelope->getMessage() instanceof YourMessage) {
return new Transport('async://');
}
return null;
}
}
Message Metadata Attach metadata to messages for tracking:
$envelope = new Envelope(new YourMessage('test'), [
How can I help you explore Laravel packages today?