Installation:
composer require alpari/messenger-bundle
Add to AppKernel.php:
new \Symfony\Bundle\MessengerBundle\MessengerBundle(),
Configure config.yml:
messenger:
transports:
async: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
'App\Message\YourMessage': async
Create a Message Class:
namespace App\Message;
class YourMessage
{
public string $content;
public function __construct(string $content) { $this->content = $content; }
}
Dispatch a Message:
use Symfony\Component\Messenger\MessageBusInterface;
class YourController
{
public function __construct(private MessageBusInterface $bus) {}
public function sendMessage()
{
$this->bus->dispatch(new YourMessage('Hello Messenger!'));
}
}
Run the Worker:
php bin/console messenger:consume async -vv
Use this bundle to offload heavy or time-consuming tasks (e.g., sending emails, processing files) to a background worker. Example:
# config.yml
messenger:
transports:
async: 'doctrine://default'
routing:
'App\Message\ProcessFile': async
// Dispatch a file processing message
$bus->dispatch(new ProcessFile('/path/to/file.pdf'));
MessageBusInterface and dispatch messages:
$this->bus->dispatch(new YourMessage($data));
public function onKernelRequest(GetResponseEvent $event)
{
$this->bus->dispatch(new LogRequestEvent($event->getRequest()));
}
messenger:
transports:
doctrine: 'doctrine://default'
messenger:
transports:
sync: 'sync://'
messenger:
transports:
amqp: '%env(AMQP_DSN)%'
Add middleware to transform, validate, or log messages:
messenger:
middleware:
- 'App\Middleware\LogMessageMiddleware'
// src/Middleware/LogMessageMiddleware.php
public function handle($message, callable $next)
{
\Log::info('Handling message: ' . get_class($message));
return $next($message);
}
Configure retry logic in config.yml:
messenger:
failure_transport: failed
transports:
failed: 'doctrine://default?queue_name=failed'
Use the CommandBus for CLI-specific messages:
messenger:
buses:
command.bus: [validation, 'App\Middleware\CliMiddleware']
Service Container:
Since Laravel uses its own DI container, manually bind the MessageBus:
$this->app->bind(MessageBusInterface::class, function ($app) {
return new MessageBus([
new HandleMessageMiddleware(),
// Add other middleware
]);
});
Configuration Overrides:
Override default config in config/messenger.php:
'transports' => [
'async' => [
'dsn' => env('MESSENGER_TRANSPORT_DSN'),
'options' => ['queue_name' => 'laravel_queue'],
],
],
Artisan Commands:
Extend Symfony's MessengerCommand for Laravel:
namespace App\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Messenger\Command\ConsumeMessagesCommand;
class ConsumeMessagesCommand extends ConsumeMessagesCommand
{
protected function getDefaultDefinition()
{
$inputDefinition = parent::getDefaultDefinition();
$inputDefinition->addOption(new \Symfony\Component\Console\Input\InputOption(
'time-limit',
null,
\InputOption::VALUE_OPTIONAL,
'Time limit in seconds',
30
));
return $inputDefinition;
}
}
Queue Workers: Use Laravel's queue system as a transport:
messenger:
transports:
laravel: 'doctrine://default?queue_name=laravel'
Then, in a worker:
$this->bus->dispatch(new YourMessage());
Symfony 2.7+ Compatibility:
MessengerBundle. Some features (e.g., DIC autoconfiguration) may not work as expected. Manually bind services if needed.MessageBus, Transport, and Router.Doctrine Transport Quirks:
doctrine/orm is compatible.sync:// for testing).Message Serialization:
__serialize() and __unserialize() for complex objects:
public function __serialize() { return ['content' => $this->content]; }
public function __unserialize(array $data) { $this->content = $data['content']; }
Serializable interface or use Symfony's SerializerComponent.Worker Process Management:
messenger:consume command runs indefinitely. Use --time-limit to avoid hanging:
php bin/console messenger:consume async --time-limit=60
Configuration Overrides:
config/messenger.php may not be auto-loaded. Ensure it’s included in config/app.php:
'config' => [
// ...
'messenger' => __DIR__.'/messenger.php',
],
Middleware Order Matters:
messenger:
middleware:
- validation
- 'App\Middleware\LogMiddleware'
Enable Debug Mode:
Run the worker with -vv for verbose output:
php bin/console messenger:consume async -vv
Check Failed Messages:
Inspect the failed transport queue:
php bin/console messenger:failed:list
php bin/console messenger:failed:retry [message-id]
Log Middleware: Add a logging middleware to trace message flow:
public function handle($message, callable $next)
{
\Log::debug('Message handled: ' . get_class($message));
return $next($message);
}
Test with Sync Transport:
Use sync:// for local testing to avoid background workers:
messenger:
transports:
sync: 'sync://'
routing:
'App\Message\*': sync
Custom Transports:
Create a custom transport by implementing TransportInterface:
class CustomTransport implements TransportInterface
{
public function get(): iterable { /* ... */ }
public function ack(Envelope $envelope) { /* ... */ }
public function reject(Envelope $envelope) { /* ... */ }
public function send(Envelope $envelope) { /* ... */ }
}
Register it in config.yml:
messenger:
transports:
custom: 'custom://'
Dynamic Routing:
Use a RouterInterface to dynamically route messages:
$router = new DynamicRouter([
new CallbackRouter([
YourMessage::class => function (MessageBusInterface $bus) {
return $bus;
},
]),
]);
Event Dispatching: Dispatch Symfony events from middleware:
public function handle($message, callable $next)
{
$event = new MessageHandledEvent($message);
$this
How can I help you explore Laravel packages today?