PHPackages                             quarks-tech/protoevent-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. quarks-tech/protoevent-php

ActiveLibrary[Queues &amp; Workers](/categories/queues)

quarks-tech/protoevent-php
==========================

PHP implementation for ProtoEvent with CloudEvents and AMQP support

2.0.8(4mo ago)03.9k↓50%1MITPHPPHP &gt;=8.0

Since Dec 26Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/quarks-tech/protoevent-php)[ Packagist](https://packagist.org/packages/quarks-tech/protoevent-php)[ RSS](/packages/quarks-tech-protoevent-php/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (10)Versions (26)Used By (1)

ProtoEvent PHP
==============

[](#protoevent-php)

PHP implementation for ProtoEvent with CloudEvents 1.0 and AMQP support.

Features
--------

[](#features)

- **CloudEvents 1.0 compliant** - Full support for CloudEvents metadata
- **Binary and Structured content modes** - Flexible message marshaling
- **Parking lot pattern** - Automatic retries with exponential backoff
- **Graceful shutdown** - Handles SIGTERM/SIGINT signals
- **Symfony integration** - Optional bundle for auto-wiring and console commands
- **Code generation** - protoc plugin generates type-safe publishers and handlers
- **In-memory transport** - For testing without RabbitMQ
- **Interceptors** - Middleware support for publishers and subscribers

Requirements
------------

[](#requirements)

- PHP 8.0+
- ext-amqp (php-amqp extension)
- RabbitMQ 3.x

Installation
------------

[](#installation)

```
composer require quarks-tech/protoevent-php
```

For Symfony, also install the required dependencies:

```
composer require symfony/config symfony/dependency-injection symfony/console symfony/http-kernel
```

Quick Start
-----------

[](#quick-start)

### Publishing Events

[](#publishing-events)

```
use QuarksTech\ProtoEvent\EventBus\Publisher;
use QuarksTech\ProtoEvent\Transport\Amqp\AmqpConnection;
use QuarksTech\ProtoEvent\Transport\Amqp\AmqpSender;

$connection = new AmqpConnection('localhost', 5672, 'guest', 'guest');
$sender = new AmqpSender($connection);
$publisher = new Publisher($sender);

// Setup exchange (once per service)
$sender->setup($serviceDesc);

// Publish using generated typed publisher
$typedPublisher = new \Your\Namespace\EventBus\Publisher($publisher);
$typedPublisher->publishYourEvent($event);
```

### Consuming Events

[](#consuming-events)

```
use QuarksTech\ProtoEvent\EventBus\Subscriber;
use QuarksTech\ProtoEvent\Transport\Amqp\AmqpConnection;
use QuarksTech\ProtoEvent\Transport\Amqp\ParkingLotReceiver;
use QuarksTech\ProtoEvent\Transport\Amqp\ParkingLotReceiverOptions;

$connection = new AmqpConnection('localhost', 5672, 'guest', 'guest');

$receiver = new ParkingLotReceiver($connection, new ParkingLotReceiverOptions(
    queueName: 'my-consumer',
    maxRetries: 3,
    retryBackoffMs: 15000,
));

$subscriber = new Subscriber('my-consumer');

// Register handlers using generated registration functions
\Your\Namespace\EventBus\Registration::registerYourEventHandler($subscriber, $handler);

// Start consuming (blocks until signal)
$subscriber->subscribe($receiver);
```

Code Generation
---------------

[](#code-generation)

Install the protoc plugin:

```
go install github.com/quarks-tech/ddkitapis-generator-go/cmd/protoc-gen-php-eventbus@latest
```

Generate code:

```
protoc --php_out=./gen --php-eventbus_out=./gen your_events.proto
```

### Generated Files

[](#generated-files)

For each proto file with event messages (marked with `(quarks_tech.protoevent.v1.enabled) = true`):

- `EventBus/ServiceDesc.php` - Service descriptor
- `EventBus/EventPublisher.php` - Typed publisher interface
- `EventBus/Publisher.php` - Publisher implementation
- `EventBus/Registration.php` - Handler registration functions
- `EventBus/Handler/*EventHandler.php` - Handler interfaces

Symfony Integration
-------------------

[](#symfony-integration)

### Bundle Registration

[](#bundle-registration)

```
// config/bundles.php
return [
    // ...
    QuarksTech\ProtoEvent\SymfonyBundle\QuarksTechProtoEventBundle::class => ['all' => true],
];
```

### Configuration

[](#configuration)

```
# config/packages/quarks_tech_proto_event.yaml
quarks_tech_proto_event:
    connection:
        dsn: '%env(RABBITMQ_DSN)%'

    queues:
        monolith.v2.subscriptions:
            parking_lot: true
            max_retries: 3

        monolith.v2.notifications:
            parking_lot: false
            prefetch_count: 10
```

### Event Handlers

[](#event-handlers)

One handler class per event. Just implement the generated interface:

```
class SubscriptionCreatedHandler implements SubscriptionCreatedEventHandler
{
    public function handleSubscriptionCreatedEvent(EventContext $ctx, SubscriptionCreatedEvent $event): void
    {
        // Handle subscription created
    }
}

class SubscriptionUpdatedHandler implements SubscriptionUpdatedEventHandler
{
    public function handleSubscriptionUpdatedEvent(EventContext $ctx, SubscriptionUpdatedEvent $event): void
    {
        // Handle subscription updated
    }
}
```

Handlers are auto-discovered. Events are routed based on type.

### Console Commands

[](#console-commands)

Run consumers for specific queues (ideal for Kubernetes deployments):

```
# Consumes SubscriptionCreated and SubscriptionUpdated events
php bin/console protoevent:consume monolith.v2.subscriptions

# Run in another pod
php bin/console protoevent:consume monolith.v2.notifications
```

All registered handlers are available to all queues. The subscriber automatically routes incoming events to the matching handler.

Testing with InMemoryTransport
------------------------------

[](#testing-with-inmemorytransport)

Use the in-memory transport for unit and integration tests:

```
use QuarksTech\ProtoEvent\EventBus\Publisher;
use QuarksTech\ProtoEvent\EventBus\Subscriber;
use QuarksTech\ProtoEvent\Transport\InMemory\InMemoryTransport;

// Create shared transport
$transport = new InMemoryTransport();

// Publisher uses transport as sender
$publisher = new Publisher($transport);

// Subscriber uses transport as receiver
$subscriber = new Subscriber('test-consumer');

// Publish events
$publisher->publish('example.v1.TestEvent', $event);

// Verify messages
$this->assertSame(1, $transport->count());
$messages = $transport->getMessages();

// Consume events
$subscriber->subscribe($transport);

// Clear for next test
$transport->clear();  // clears messages only
$transport->reset();  // clears messages and services
```

Interceptors
------------

[](#interceptors)

Add cross-cutting concerns with interceptors:

```
use QuarksTech\ProtoEvent\EventBus\PublisherInterceptor;
use QuarksTech\ProtoEvent\EventBus\SubscriberInterceptor;

// Publisher interceptor
class TracingPublisherInterceptor implements PublisherInterceptor
{
    public function intercept(Metadata $metadata, Message $event, callable $next): void
    {
        $metadata = $metadata->withExtension('traceid', $this->traceId);
        $next($metadata, $event);
    }
}

// Subscriber interceptor
class LoggingSubscriberInterceptor implements SubscriberInterceptor
{
    public function intercept(EventContext $context, mixed $event, callable $next): void
    {
        $this->logger->info('Processing: ' . $context->getMetadata()->getType());
        $next($context, $event);
    }
}

// Add to publisher/subscriber
$publisher->withInterceptor(new TracingPublisherInterceptor($tracer));
$subscriber->withInterceptor(new LoggingSubscriberInterceptor($logger));
```

Architecture
------------

[](#architecture)

### Parking Lot Pattern

[](#parking-lot-pattern)

Failed messages flow through a retry cycle:

```
Main Queue → DLX → Wait Queue (TTL) → DLX → Main Queue (retry)
                                         ↓
                        (max retries) → Parking Lot Queue

```

Queue naming:

- `{queue}` - main processing queue
- `{queue}.wait` - wait queue with TTL backoff
- `{queue}.pl` - parking lot for permanently failed messages
- `{queue}.dlx` - dead letter exchange

### Message Marshaling

[](#message-marshaling)

**Binary mode** (default): CloudEvents attributes in AMQP headers, payload in body.

**Structured mode**: Full CloudEvents JSON document in message body (use content type `application/cloudevents+json`).

Notes:

- Setting `application/cloudevents+json` implies **JSON payload encoding** (protobuf JSON for protobuf messages), matching the Go implementation.
- Timestamps are emitted as **RFC3339 without fractional seconds** for cross-language compatibility.

License
-------

[](#license)

MIT

###  Health Score

48

—

FairBetter than 95% of packages

Maintenance82

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~50 days

Recently: every ~0 days

Total

23

Last Release

126d ago

Major Versions

0.1.0 → 2.0.02026-01-07

PHP version history (2 changes)1.0.0PHP &gt;=8

2.0.0PHP &gt;=8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/7346c6525512fc0ccfff1b2f7abec422ab7f70ed7ef737d7b230fee8f08d5e1f?d=identicon)[oleg-ozimok](/maintainers/oleg-ozimok)

---

Top Contributors

[![andrii-kaidash-quarks-tech](https://avatars.githubusercontent.com/u/123075491?v=4)](https://github.com/andrii-kaidash-quarks-tech "andrii-kaidash-quarks-tech (18 commits)")[![f1r3starter](https://avatars.githubusercontent.com/u/4527229?v=4)](https://github.com/f1r3starter "f1r3starter (11 commits)")[![constantin-gordienko-quarks-tech](https://avatars.githubusercontent.com/u/122791860?v=4)](https://github.com/constantin-gordienko-quarks-tech "constantin-gordienko-quarks-tech (7 commits)")[![r0nder](https://avatars.githubusercontent.com/u/570896?v=4)](https://github.com/r0nder "r0nder (7 commits)")[![artem-sakhan-quarks-tech](https://avatars.githubusercontent.com/u/122793526?v=4)](https://github.com/artem-sakhan-quarks-tech "artem-sakhan-quarks-tech (5 commits)")[![andrey-filenko-quarks-tech](https://avatars.githubusercontent.com/u/122791524?v=4)](https://github.com/andrey-filenko-quarks-tech "andrey-filenko-quarks-tech (2 commits)")[![oleh-ozimok](https://avatars.githubusercontent.com/u/9019062?v=4)](https://github.com/oleh-ozimok "oleh-ozimok (1 commits)")

---

Tags

symfonyeventsprotobufrabbitmqAMQPevent buscloudevents

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/quarks-tech-protoevent-php/health.svg)

```
[![Health](https://phpackages.com/badges/quarks-tech-protoevent-php/health.svg)](https://phpackages.com/packages/quarks-tech-protoevent-php)
```

###  Alternatives

[php-amqplib/rabbitmq-bundle

Integrates php-amqplib with Symfony &amp; RabbitMq. Formerly emag-tech-labs/rabbitmq-bundle, oldsound/rabbitmq-bundle.

1.3k20.1M65](/packages/php-amqplib-rabbitmq-bundle)[enqueue/enqueue

Message Queue Library

19820.0M56](/packages/enqueue-enqueue)[nuwber/rabbitevents

The Nuwber RabbitEvents package

120515.8k3](/packages/nuwber-rabbitevents)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
