|
| 1 | +# Message Broker with Ecotone - RabbitMQ, Kafka, SQS, Redis |
| 2 | + |
| 3 | +This example demonstrates how incredibly easy it is to set up **asynchronous messaging** with a message broker using [Ecotone Framework](https://ecotone.tech). With just a few lines of code, you can publish and consume messages from **RabbitMQ**, and switch to **Kafka**, **Amazon SQS**, **Redis**, or **Database (DBAL)** with a single line change. |
| 4 | + |
| 5 | +## Quick Start |
| 6 | + |
| 7 | +```bash |
| 8 | +# Install dependencies |
| 9 | +composer install |
| 10 | + |
| 11 | +# Run publisher (sends message to RabbitMQ) |
| 12 | +php publisher.php |
| 13 | + |
| 14 | +# Run consumer (receives and processes message) |
| 15 | +php consumer.php |
| 16 | +``` |
| 17 | + |
| 18 | +**Output:** |
| 19 | +``` |
| 20 | +Message sent to queue 'orders' |
| 21 | +Starting consumer for queue 'orders'... |
| 22 | +Processing order 123: Milk |
| 23 | +Consumer finished. |
| 24 | +``` |
| 25 | + |
| 26 | +## Why Ecotone Makes It Easy |
| 27 | + |
| 28 | +### 1. Single Line Channel Configuration |
| 29 | + |
| 30 | +Setting up a RabbitMQ-backed message channel requires just **one line**: |
| 31 | + |
| 32 | +```php |
| 33 | +AmqpBackedMessageChannelBuilder::create('orders') |
| 34 | +``` |
| 35 | + |
| 36 | +That's it. No complex queue bindings, no exchange declarations, no consumer configuration. Ecotone handles everything. |
| 37 | + |
| 38 | +### 2. Switch Message Brokers Instantly |
| 39 | + |
| 40 | +Want to use a different message broker? Just change the channel builder: |
| 41 | + |
| 42 | +| Message Broker | Configuration | Package | |
| 43 | +|----------------|---------------|---------| |
| 44 | +| **RabbitMQ** | `AmqpBackedMessageChannelBuilder::create('orders')` | `ecotone/amqp` | |
| 45 | +| **Amazon SQS** | `SqsBackedMessageChannelBuilder::create('orders')` | `ecotone/sqs` | |
| 46 | +| **Redis** | `RedisBackedMessageChannelBuilder::create('orders')` | `ecotone/redis` | |
| 47 | +| **Kafka** | `KafkaMessageChannelBuilder::create('orders')` | `ecotone/kafka` | |
| 48 | +| **Database** | `DbalBackedMessageChannelBuilder::create('orders')` | `ecotone/dbal` | |
| 49 | + |
| 50 | +Your business logic remains **completely unchanged**. The `#[Asynchronous('orders')]` attribute works with any of these brokers. |
| 51 | + |
| 52 | +### 3. Type-Safe Commands |
| 53 | + |
| 54 | +Use proper PHP classes for your messages instead of raw arrays: |
| 55 | + |
| 56 | +```php |
| 57 | +class PlaceOrder |
| 58 | +{ |
| 59 | + public function __construct( |
| 60 | + public string $orderId, |
| 61 | + public string $product |
| 62 | + ) {} |
| 63 | +} |
| 64 | + |
| 65 | +// Send type-safe command |
| 66 | +$ecotone->getCommandBus()->send(new PlaceOrder('123', 'Milk')); |
| 67 | +``` |
| 68 | + |
| 69 | +Ecotone automatically serializes and deserializes your objects. |
| 70 | + |
| 71 | +## How It Works Under the Hood |
| 72 | + |
| 73 | +### Publishing Flow |
| 74 | + |
| 75 | +1. **Send Command** → `CommandBus::send(new PlaceOrder(...))` |
| 76 | +2. **Serialize** → Command is converted to JSON (or other format) |
| 77 | +3. **Publish** → Message is sent to RabbitMQ queue named `orders` |
| 78 | + |
| 79 | +### Consuming Flow |
| 80 | + |
| 81 | +1. **Poll** → Consumer calls `$ecotone->run('orders')` |
| 82 | +2. **Receive** → Message is fetched from RabbitMQ queue |
| 83 | +3. **Deserialize** → JSON is converted back to `PlaceOrder` object |
| 84 | +4. **Invoke Handler** → `OrderHandler::handle(PlaceOrder $command)` is called |
| 85 | +5. **Acknowledge** → Message is removed from queue on success |
| 86 | + |
| 87 | +### The Asynchronous Attribute |
| 88 | + |
| 89 | +```php |
| 90 | +#[Asynchronous('orders')] |
| 91 | +#[CommandHandler(endpointId: 'orderHandler')] |
| 92 | +public function handle(PlaceOrder $command): void |
| 93 | +{ |
| 94 | + // This runs in the consumer process, not the publisher |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +- `#[Asynchronous('orders')]` - Routes the command to the `orders` message channel |
| 99 | +- `#[CommandHandler]` - Registers this method as a command handler |
| 100 | +- `endpointId` - Unique identifier for this endpoint (required for async handlers) |
| 101 | + |
| 102 | +### Message Channel Architecture |
| 103 | + |
| 104 | +``` |
| 105 | +┌──────────────┐ ┌─────────────────┐ ┌──────────────┐ |
| 106 | +│ Publisher │────▶│ Message Broker │────▶│ Consumer │ |
| 107 | +│ (PHP CLI) │ │ (RabbitMQ) │ │ (PHP CLI) │ |
| 108 | +└──────────────┘ └─────────────────┘ └──────────────┘ |
| 109 | + │ │ |
| 110 | + ▼ ▼ |
| 111 | + CommandBus CommandHandler |
| 112 | + .send(PlaceOrder) .handle(PlaceOrder) |
| 113 | +``` |
| 114 | + |
| 115 | +## Try It Yourself |
| 116 | + |
| 117 | +1. **Clone this repository** and run the example |
| 118 | +2. **Check RabbitMQ Management UI** at `http://localhost:15672` (guest/guest) |
| 119 | +3. **Modify the handler** to see how messages are processed |
| 120 | +4. **Switch to a different broker** by changing one line |
| 121 | + |
| 122 | +## Learn More |
| 123 | + |
| 124 | +- 📚 [Ecotone Documentation](https://docs.ecotone.tech) |
| 125 | + |
| 126 | +## Keywords |
| 127 | + |
| 128 | +PHP Message Queue, RabbitMQ PHP, Kafka PHP, Amazon SQS PHP, Redis Pub/Sub PHP, Async PHP, PHP Message Broker, PHP Event-Driven Architecture, CQRS PHP, PHP Microservices, Ecotone Framework, PHP Messaging, Asynchronous PHP Processing, PHP Queue System, PHP Event Bus |
0 commit comments