A package for working with RabbitMQ messages as Laravel events. Automatically serialize and publish events to RabbitMQ, and consume messages from queues by converting them back into events.
Automatic event serialization — Events implementing the Broadcast interface are automatically serialized and sent to RabbitMQ
Message consumption — Command to consume messages from RabbitMQ with automatic deserialization and event dispatching
Default bindings — The BroadcastEvent trait sets standard connection parameters for an event
Flexible configuration — Support for multiple connections and parameterization for each event
Microservices architecture — Ideal for data exchange between services
- PHP 8.1+
- Laravel 10, 11 or 12
- RabbitMQ server
Install via Composer:
composer require diffhead/laravel-rabbitmqThe package will be automatically registered thanks to Laravel Service Provider Discovery.
Publish the configuration file:
php artisan vendor:publish --provider="Diffhead\PHP\LaravelRabbitMQ\ServiceProvider"ThisEnvironment Variables
# RabbitMQ Connection
RABBITMQ_HOST=localhost
RABBITMQ_PORT=5672
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_VHOST=/
# Default event parameters
RABBITMQ_EVENT_CONNECTION=default
RABBITMQ_EVENT_QUEUE=default
RABBITMQ_EVENT_EXCHANGE=amq.direct
RABBITMQ_EVENT_EXCHANGE_TYPE=direct
RABBITMQ_EVENT_EXCHANGE_IS_DEFAULT=true
RABBITMQ_EVENT_ROUTING_KEY=return [
'connections' => [
'default' => [
'host' => env('RABBITMQ_HOST', 'localhost'),
'port' => env('RABBITMQ_PORT', 5672),
'user' => env('RABBITMQ_USER', 'guest'),
'password' => env('RABBITMQ_PASSWORD', 'guest'),
'vhost' => env('RABBITMQ_VHOST', '/'),
],
'secondary' => [
'host' => env('RABBITMQ_SECONDARY_HOST', 'localhost'),
'port' => env('RABBITMQ_SECONDARY_PORT', 5672),
'user' => env('RABBITMQ_SECONDARY_USER', 'guest'),
'password' => env('RABBITMQ_SECONDARY_PASSWORD', 'guest'),
'vhost' => env('RABBITMQ_SECONDARY_VHOST', '/'),
]
],
'message' => [
'serializer' => \Diffhead\PHP\LaravelRabbitMQ\Service\Serializer::class,
'unserializer' => \Diffhead\PHP\LaravelRabbitMQ\Service\Unserializer::class,
],
'event' => [
'defaults' => [
'connection' => env('RABBITMQ_EVENT_CONNECTION', 'default'),
'queue' => env('RABBITMQ_EVENT_QUEUE', 'default'),
'exchange' => env('RABBITMQ_EVENT_EXCHANGE', 'amq.direct'),
'exchange_type' => env('RABBITMQ_EVENT_EXCHANGE_TYPE', 'direct'),
'exchange_is_default' => (bool) env('RABBITMQ_EVENT_EXCHANGE_IS_DEFAULT', true),
'routing_key' => env('RABBITMQ_EVENT_ROUTING_KEY', ''),
],
'mapper' => \Diffhead\PHP\LaravelRabbitMQ\Service\EventMapper::class,
'map' => [
/**
* Map events to queues and routing keys
*/
\App\Events\User\UserCreated::class => [
'queues' => ['portal.users'],
'routing_keys' => ['user.created'],
],
\App\Events\Meeting\MeetingCreated::class => [
'queues' => ['portal.meetings'],
'routing_keys' => ['meeting.created'],
],
],
]
];Create an event that implements the Broadcast interface:
namespace App\Events;
use Diffhead\PHP\LaravelRabbitMQ\Event\Broadcast;
use Diffhead\PHP\LaravelRabbitMQ\Trait\BroadcastEvent;
use Illuminate\Foundation\Events\Dispatchable;
class UserCreated implements Broadcast
{
use Dispatchable, BroadcastEvent;
public function __construct(
public int $userId,
public string $email,
public string $name,
) {}
public function jsonSerialize(): array
{
return [
'userId' => $this->userId,
'email' => $this->email,
'name' => $this->name,
];
}
}When implementing the Broadcast interface, you must define the following methods:
getConnection(): string— RabbitMQ connection namegetQueue(): string— Queue namegetExchange(): string— Exchange namegetExchangeType(): string— Exchange type (direct, topic, fanout, headers)getExchangeIsDefault(): bool— Whether to use the default exchangegetRoutingKey(): string— Routing key for the message
The BroadcastEvent trait provides implementations of all methods using default parameters from configuration:
namespace App\Events;
use Diffhead\PHP\LaravelRabbitMQ\Event\Broadcast;
use Diffhead\PHP\LaravelRabbitMQ\Trait\BroadcastEvent;
class UserCreated implements Broadcast
{
use BroadcastEvent;
public function __construct(
public int $userId,
public string $email,
) {}
public function jsonSerialize(): array
{
return [
'userId' => $this->userId,
'email' => $this->email,
];
}
}If you need special parameters for a specific event, override the necessary methods:
namespace App\Events;
use Diffhead\PHP\LaravelRabbitMQ\Event\Broadcast;
use Diffhead\PHP\LaravelRabbitMQ\Trait\BroadcastEvent;
class CriticalAlert implements Broadcast
{
use BroadcastEvent;
public function __construct(
public string $message,
) {}
public function getRoutingKey(): string
{
return 'alert.critical';
}
public function getExchange(): string
{
return 'alerts.topic';
}
public function getExchangeType(): string
{
return 'topic';
}
public function jsonSerialize(): array
{
return [
'message' => $this->message,
];
}
}Events are automatically published when dispatched:
use App\Events\UserCreated;
/**
* Events implementing Broadcast are automatically sent to RabbitMQ
*/
UserCreated::dispatch(userId: 1, email: 'user@example.com', name: 'John Doe');Use the rabbitmq:consume command to listen for messages:
#####################################################################################
#
# Has following options:
#
# --connection=default - Connection name from config
# --queue=default - Queue
# --exchange=amq.direct - Exchange name
# --exchange-type=direct - Exchange type
# --exchange-is-default - Exchange is default, required for default exchanges
# --routing-key=user.* - Listen routing keys, required for topic exchanges
# --tag=myconsumer - Consumer tag for rabbitmq
#
#####################################################################################
php artisan rabbitmq:consumephp artisan rabbitmq:consume \
--connection=default \
--queue=service.users \
--exchange=amq.direct \
--exchange-type=direct \
--routing-key=user.* \
--tag=service-users-consumerWhen a message is received from RabbitMQ, it is automatically deserialized and dispatched as a Laravel event. You can listen to these events normally:
namespace App\Listeners;
use App\Events\UserCreated;
use Illuminate\Support\Log;
class SendWelcomeEmail
{
public function handle(UserCreated $event): void
{
Log::info("User created: {$event->email}");
}
}Register the listener in app/Providers/EventServiceProvider.php:
protected $listen = [
\App\Events\UserCreated::class => [
\App\Listeners\SendWelcomeEmail::class,
],
];Laravel Event (Broadcast)
↓
PublishEvent (Listener)
↓
Serializer (JSON)
↓
RabbitMQ Exchange
↓
Queue
RabbitMQ Queue
↓
Message Consumer
↓
Unserializer (JSON)
↓
EventMapper (Event)
↓
EventEmitter (Service)
↓
Event Listeners
namespace App\Events;
use Diffhead\PHP\LaravelRabbitMQ\Event\Broadcast;
use Diffhead\PHP\LaravelRabbitMQ\Trait\BroadcastEvent;
class UserCreated implements Broadcast
{
use BroadcastEvent;
public function __construct(
public int $id,
public string $email,
public string $name,
) {}
public function getRoutingKey(): string
{
return 'user.created';
}
public function jsonSerialize(): array
{
return [
'id' => $this->id,
'email' => $this->email,
'name' => $this->name,
];
}
}use App\Events\UserCreated;
/**
* Controller method
*/
public function store(Request $request)
{
$user = User::create($request->validated());
UserCreated::dispatch($user->id, $user->email, $user->name);
return response()->json($user, 201);
}Map event using configuration:
'map' => [
\App\Events\UserCreated::class => [
'queues' => ['service2.users'],
'routing_keys' => ['user.created']
]
]Then implement and register event listener:
namespace App\Listeners;
use App\Events\UserCreated;
class SyncUserToCalendar
{
public function handle(UserCreated $event): void
{
CalendarUser::create([
'external_id' => $event->id,
'email' => $event->email,
'name' => $event->name,
]);
}
}Start consumer
php artisan rabbitmq:consume --queue=service2.users --routing-key=user.* --exchange=amq.topic --exchange-type=topic --exchange-is-defaultThe package uses JSON for serialization/deserialization of data via Serializer and Unserializer interfaces.
You can use your own serialization classes by implementing interfaces and overriding following configuration entities:
'message' => [
'serializer' => \App\Services\CustomSerializer::class,
'unserializer' => \App\Services\CustomUnserializer::class,
],The package maps rabbitmq message to application events
You can use your own mapping logic by implementing EventMapper
interface and overriding the following configuration entity:
'event' => [
'mapper' => \App\Services\CustomEventMapper::class,
]