SkillAgentSearch skills...

Rabbitevents

Laravel Microservices Event Bus using RabbitMQ. Seamlessly publish events and handle them across distributed systems.

Install / Use

/learn @nuwber/Rabbitevents
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

RabbitEvents

Tests Status codecov Total Downloads Latest Version License

Let's imagine a use case: a User made a payment. You need to handle this payment, register the user, send him emails, send analytics data to your analysis system, and so on. The modern infrastructure requires you to create microservices that do their specific job and only it: one handles payments, one is for user management, one is the mailing system, one is for analysis. How to let all of them know that a payment succeeded and handle this message? The answer is "To use RabbitEvents".

Once again, the RabbitEvents library helps you publish an event and handle it in another app. It doesn't make sense to use it in the same app because Laravel's Events work better for that.

Demo

rabbit-events-demo

Table of Contents

  1. Installation via Composer
  2. Upgrade from 8.x to 9.x
  3. Publisher component
  4. Listener component
  5. Listeners & Payloads
  6. Custom Serializers
  7. Extensions
  8. Examples
  9. Speeding up RabbitEvents
  10. Testing
  11. Non-standard use
  12. License

Installation via Composer<a name="installation"></a>

You can use Composer to install RabbitEvents into your Laravel project:

composer require nuwber/rabbitevents

Configuration<a name="configuration"></a>

After installing RabbitEvents, publish its config and a service provider using the rabbitevents:install Artisan command:

php artisan rabbitevents:install

This command installs the config file at config/rabbitevents.php and the Service Provider file at app/providers/RabbitEventsServiceProvider.php.

The config file is very similar to the queue connection, but with the separate config, you'll never be confused if you have another connection to RabbitMQ.

<?php
use Enqueue\AmqpTools\RabbitMqDlxDelayStrategy;

return [
    'default' => env('RABBITEVENTS_CONNECTION', 'rabbitmq'),

    /*
    |--------------------------------------------------------------------------
    | Default Serializer
    |--------------------------------------------------------------------------
    |
    | The default serializer to use when publishing messages.
    | Supported: "json", "protobuf" or any class implementing Serializer interface.
    |
    */
    'default_serializer' => \RabbitEvents\Foundation\Serialization\JsonSerializer::class,

    'connections' => [
        'rabbitmq' => [
            'driver' => 'rabbitmq',
            'exchange' => env('RABBITEVENTS_EXCHANGE', 'events'),
            'durable' => env('RABBITEVENTS_QUEUE_DURABLE', true),
            'host' => env('RABBITEVENTS_HOST', 'localhost'),
            'port' => env('RABBITEVENTS_PORT', 5672),
            'user' => env('RABBITEVENTS_USER', 'guest'),
            'pass' => env('RABBITEVENTS_PASSWORD', 'guest'),
            'vhost' => env('RABBITEVENTS_VHOST', 'events'),
            'delay_strategy' => env('RABBITEVENTS_DELAY_STRATEGY', RabbitMqDlxDelayStrategy::class),
            'ssl' => [
                'is_enabled' => env('RABBITEVENTS_SSL_ENABLED', false),
                'verify_peer' => env('RABBITEVENTS_SSL_VERIFY_PEER', true),
                'cafile' => env('RABBITEVENTS_SSL_CAFILE'),
                'local_cert' => env('RABBITEVENTS_SSL_LOCAL_CERT'),
                'local_key' => env('RABBITEVENTS_SSL_LOCAL_KEY'),
                'passphrase' => env('RABBITEVENTS_SSL_PASSPHRASE', ''),
            ],
            'read_timeout' => env('RABBITEVENTS_READ_TIMEOUT', 3.),
            'write_timeout' => env('RABBITEVENTS_WRITE_TIMEOUT', 3.),
            'connection_timeout' => env('RABBITEVENTS_CONNECTION_TIMEOUT', 3.),
            'heartbeat' => env('RABBITEVENTS_HEARTBEAT', 0),
            'persisted' => env('RABBITEVENTS_PERSISTED', false),
            'lazy' => env('RABBITEVENTS_LAZY', true),
            'qos' => [
                'global' => env('RABBITEVENTS_QOS_GLOBAL', false),
                'prefetch_size' => env('RABBITEVENTS_QOS_PREFETCH_SIZE', 0),
                'prefetch_count' => env('RABBITEVENTS_QOS_PREFETCH_COUNT', 1),
            ]
        ],
    ],
    'logging' => [
        'enabled' => env('RABBITEVENTS_LOG_ENABLED', false),
        'level' => env('RABBITEVENTS_LOG_LEVEL', 'info'),
        'channel' => env('RABBITEVENTS_LOG_CHANNEL'),
    ],
];

Upgrade from 8.x to 9.x<a name="upgrade_8.x-9.x"></a>

PHP 8.2 required

RabbitEvents now requires PHP 8.2 or greater. It uses readonly classes and Enums.

Payload System Refactor

The internal payload handling has been refactored. Message::payload() now returns a RabbitEvents\Foundation\Contracts\Payload object. To get the raw value, use $message->payload->value().

Protobuf Support

RabbitEvents supports Google Protobuf messages via the rabbitevents/protobuf extension package. Once installed, simply publish a Protobuf Message object, and it will be automatically serialized and hydrated on the listener side. The system uses the type AMQP header to resolve the correct class.

Example:

use Google\Protobuf\StringValue;

+$message = new StringValue();
+$message->setValue('Hello World');
+
+publish('my.event', $message);

Dynamic Serializers

The correct serializer is now automatically selected based on the content_type header of the message.

  • application/json -> JSON Serializer
  • application/x-protobuf -> Protobuf Serializer

Supported Laravel versions

RabbitEvents now supports Laravel 10.0 or greater.

Architecture Decoupling

Version 9.0 introduces a more abstract and extensible architecture.

  • Decoupled Serialization: Serializers now use an abstract TransportMessage contract instead of Interop\Amqp\AmqpMessage. This creates a cleaner separation between domain logic and the transport layer.
  • Abstract Message Factory: The MessageFactory has been moved to the Foundation layer and is now pluggable. You can implement your own TransportMessageFactory to create messages from different sources (e.g., tailored for testing or other transports).
  • Transport Agnostic: The core Message and Sender classes rely on internal contracts (RabbitEvents\Foundation\Contracts\*), avoiding strict dependencies on queue-interop. Adapters are provided for AMQP.
  • Connection Class Moved: RabbitEvents\Foundation\Connection has been moved to RabbitEvents\Foundation\Amqp\Connection. Update your type hints if you were using it directly.

Namespace Changes

We have reorganized the namespace structure for better clarity and standard compliance:

  • Commands: All console commands have been moved to Console namespaces.
    • RabbitEvents\Foundation\Commands -> RabbitEvents\Foundation\Console
    • RabbitEvents\Listener\Commands -> RabbitEvents\Listener\Console
    • RabbitEvents\Publisher\Commands -> RabbitEvents\Publisher\Console
  • Releaser: RabbitEvents\Foundation\Support\Releaser has been moved to RabbitEvents\Listener\Support\Releaser as it is a listener-specific component.

Removed --connection option from the rabbitevents:listen command

The default connection is always used instead.

RabbitEvents Publisher<a name="publisher"></a>

The RabbitEvents Publisher component provides an API to publish events across the application structure. More information about how it works can be found on the RabbitEvents Publisher page.

RabbitEvents Listener<a name="listener"></a>

The RabbitEvents Listener component provides an API to handle events that were published across the application structure. More information about how it works can be found on the RabbitEvents Listener page.

It supports:

  • Manual Registration: using the $listen array.
  • Attributes: using #[Listener] on classes or methods.
  • Auto-Discovery: automatically finding #[Listener] attributes in your listeners directory.

Listeners & Payloads<a name="listeners-payloads"></a>

How the payload is passed to your listener depends on the serialization format:

JSON (Default): The payload is decoded as an associative array.

public function handle(array $payload) {
    // $payload['key']
}

Protobuf: The payload is passed as the Message Object itself.

public function handle(\Google\Protobuf\Internal\Message $message) {
    // $message->getSomething()
}

Custom Serializers<a name="custom-serializers"></a>

You can implement your own serializer by implementing RabbitEvents\Foundation\Contracts\Serializer and RabbitEvents\Foundation\Contracts\ContentType.

use RabbitEvents\Foundation\Contracts\Serializer;
use RabbitEvents\Foundation\Contracts\ContentType;
use RabbitEvents\Foundation\Contracts\Payload;

class MySerializer implements Serializer
{
    public function serialize($data): Payload { ... }
    public function deserialize($message): Payload { ... }
    public function contentType(): Cont

Related Skills

View on GitHub
GitHub Stars120
CategoryDevelopment
Updated16d ago
Forks35

Languages

PHP

Security Score

100/100

Audited on Mar 17, 2026

No findings