This is an automated email from the ASF dual-hosted git repository.
hubcio pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new ff74972d4 feat(php): add PHP message envelope example (#4718)
ff74972d4 is described below
commit ff74972d449752bc5b5d18ecf38eeeb2d90ba152
Author: Abhinav Negi <[email protected]>
AuthorDate: Thu Nov 5 14:59:47 2026 +0530
feat(php): add PHP message envelope example (#4718)
---
examples/php/README.md | 13 ++++
examples/php/message-envelope/consumer.php | 108 +++++++++++++++++++++++++++++
examples/php/message-envelope/producer.php | 78 +++++++++++++++++++++
3 files changed, 199 insertions(+)
diff --git a/examples/php/README.md b/examples/php/README.md
index b1f2b7f5b..cd2abe716 100644
--- a/examples/php/README.md
+++ b/examples/php/README.md
@@ -34,6 +34,19 @@ php -d
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_p
php -d
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}"
basic/consumer.php
```
+### Message Envelopes
+
+The message envelope pattern wraps each payload in a JSON object with a
+`message_type` and a `payload` string, so one topic can carry several kinds of
+messages. The producer sends `OrderCreated`, `OrderConfirmed` and
+`OrderRejected` messages, and the consumer dispatches on `message_type`. A
+message with an unknown type is logged and skipped.
+
+```bash
+php -d
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}"
message-envelope/producer.php
+php -d
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}"
message-envelope/consumer.php
+```
+
The examples use `IGGY_CONNECTION_STRING` when it is set; use a binary
transport
with credentials for automatic login. Otherwise they connect over TCP using
`IGGY_HOST` and `IGGY_PORT`, then log in with `IGGY_USERNAME` and
`IGGY_PASSWORD`
diff --git a/examples/php/message-envelope/consumer.php
b/examples/php/message-envelope/consumer.php
new file mode 100644
index 000000000..1a31ae9e4
--- /dev/null
+++ b/examples/php/message-envelope/consumer.php
@@ -0,0 +1,108 @@
+<?php
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+declare(strict_types=1);
+
+require_once __DIR__ . '/../src/common.php';
+
+use Iggy\CommitPolicy;
+use Iggy\PollingStrategy;
+use Iggy\PollOptions;
+
+const ORDER_CREATED_TYPE = 'OrderCreated';
+const ORDER_CONFIRMED_TYPE = 'OrderConfirmed';
+const ORDER_REJECTED_TYPE = 'OrderRejected';
+
+const MESSAGES_PER_POLL = 10;
+
+function log_line(string $message): void
+{
+ echo $message, PHP_EOL;
+}
+
+/**
+ * Decodes the inner payload, which the envelope carries as a JSON string.
+ */
+function decode_payload(string $payload): array
+{
+ $decoded = json_decode($payload, true, 512, JSON_THROW_ON_ERROR);
+ if (!is_array($decoded)) {
+ throw new UnexpectedValueException('Envelope payload is not a JSON
object');
+ }
+
+ return $decoded;
+}
+
+function handle_message(string $raw): void
+{
+ try {
+ // The message envelope lets one topic carry different message types.
+ $envelope = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
+ if (
+ !is_array($envelope)
+ || !is_string($envelope['message_type'] ?? null)
+ || !is_string($envelope['payload'] ?? null)
+ ) {
+ throw new UnexpectedValueException('Envelope must contain string
"message_type" and "payload"');
+ }
+
+ $messageType = $envelope['message_type'];
+ log_line("Handling message type: {$messageType}...");
+
+ match ($messageType) {
+ ORDER_CREATED_TYPE => log_line(
+ 'Order Created: ' .
json_encode(decode_payload($envelope['payload'])),
+ ),
+ ORDER_CONFIRMED_TYPE => log_line(
+ 'Order Confirmed: ' .
json_encode(decode_payload($envelope['payload'])),
+ ),
+ ORDER_REJECTED_TYPE => log_line(
+ 'Order Rejected: ' .
json_encode(decode_payload($envelope['payload'])),
+ ),
+ default => log_line("Received unknown message type:
{$messageType}, skipping"),
+ };
+ } catch (JsonException | UnexpectedValueException $e) {
+ log_line('Skipping malformed message: ' . $e->getMessage());
+ }
+}
+
+$stream = 'php-message-envelope-stream';
+$topic = 'php-message-envelope-topic';
+$client = iggy_client();
+
+ensure_stream_and_topic($client, $stream, $topic);
+
+$messages = $client->pollMessages(
+ $stream,
+ $topic,
+ 0,
+ CONSUMER_ID,
+ PollingStrategy::first(),
+ new PollOptions(count: MESSAGES_PER_POLL, commit: CommitPolicy::onRead()),
+)->messages;
+
+if (count($messages) === 0) {
+ log_line('No messages available. Run producer.php first.');
+ exit(0);
+}
+
+foreach ($messages as $message) {
+ handle_message($message->payload());
+}
+
+log_line('Consumed ' . count($messages) . ' message(s).');
diff --git a/examples/php/message-envelope/producer.php
b/examples/php/message-envelope/producer.php
new file mode 100644
index 000000000..964c430e5
--- /dev/null
+++ b/examples/php/message-envelope/producer.php
@@ -0,0 +1,78 @@
+<?php
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+declare(strict_types=1);
+
+require_once __DIR__ . '/../src/common.php';
+
+const ORDER_CREATED_TYPE = 'OrderCreated';
+const ORDER_CONFIRMED_TYPE = 'OrderConfirmed';
+const ORDER_REJECTED_TYPE = 'OrderRejected';
+
+const MESSAGES_COUNT = 6;
+
+/**
+ * Wraps a payload in a message envelope. The envelope carries the message type
+ * and the payload as a JSON string, so a single topic can hold several kinds
+ * of messages.
+ */
+function to_json_envelope(string $messageType, array $payload): string
+{
+ return json_encode([
+ 'message_type' => $messageType,
+ 'payload' => json_encode($payload, JSON_THROW_ON_ERROR),
+ ], JSON_THROW_ON_ERROR);
+}
+
+function generate_envelope(int $orderId): string
+{
+ return match ($orderId % 3) {
+ 0 => to_json_envelope(ORDER_CREATED_TYPE, [
+ 'orderId' => "order-{$orderId}",
+ 'customerId' => 'customer-' . random_int(0, 99),
+ 'amount' => random_int(0, 9999),
+ ]),
+ 1 => to_json_envelope(ORDER_CONFIRMED_TYPE, [
+ 'orderId' => 'order-' . intdiv($orderId, 3),
+ 'timestamp' => (int) (microtime(true) * 1000),
+ ]),
+ default => to_json_envelope(ORDER_REJECTED_TYPE, [
+ 'orderId' => 'order-' . intdiv($orderId, 3),
+ 'reason' => 'Insufficient balance',
+ ]),
+ };
+}
+
+$stream = 'php-message-envelope-stream';
+$topic = 'php-message-envelope-topic';
+$client = iggy_client();
+
+ensure_stream_and_topic($client, $stream, $topic);
+
+$payloads = array_map(
+ static fn (int $orderId): string => generate_envelope($orderId),
+ range(1, MESSAGES_COUNT),
+);
+
+foreach ($payloads as $payload) {
+ echo "Sending envelope: {$payload}", PHP_EOL;
+}
+
+send_payloads($client, $stream, $topic, $payloads);
+
+echo 'Sent ' . MESSAGES_COUNT . ' PHP message envelopes', PHP_EOL;