Publish and receive messages with topics

Updated at:

This example walks through the complete topic-based messaging lifecycle with the Simple Message Queue (formerly MNS) SDK for PHP: create a topic, subscribe a queue endpoint, publish messages, receive them, and clean up resources.

All steps use the same client instance created in the Set up the client section. For the complete runnable file, see CreateTopicAndPushMessageToQueue.php on GitHub.

Prerequisites

Before you begin, make sure that you have:

Set up the client

All operations in this example require an SMQ client instance. Create the client with your endpoint and access credentials:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use AliyunMNS\Client;
use AliyunMNS\Constants;
use AliyunMNS\Exception\MessageNotExistException;
use AliyunMNS\Model\SubscriptionAttributes;
use AliyunMNS\Requests\PublishBase64MessageRequest;
use AliyunMNS\Requests\PublishMessageRequest;
use AliyunMNS\Requests\CreateTopicRequest;
use AliyunMNS\Requests\CreateQueueRequest;
use AliyunMNS\Exception\MnsException;

// Load credentials from environment variables.
// For credential configuration, see: https://www.alibabacloud.com/help/en/mns/developer-reference/php-configure-access-domain-names-and-credentials
$accessId = getenv(Constants::ALIYUN_AK_ENV_KEY);
$accessKey = getenv(Constants::ALIYUN_SK_ENV_KEY);
$endPoint = "<your-endpoint>";  // Example: https://1234567890123456.mns.cn-hangzhou.aliyuncs.com

$client = new Client($endPoint, $accessId, $accessKey);

Replace the following placeholder with your actual value:

PlaceholderDescriptionExample
<your-endpoint>Your SMQ endpoint URLhttps://1234567890123456.mns.cn-hangzhou.aliyuncs.com

Step 1: Create a topic

Create a topic that serves as the message channel. Messages published to this topic are delivered to all subscribers.

$topicName = "MyTopicExample";
$request = new CreateTopicRequest($topicName);

try {
    $res = $client->createTopic($request);
    echo "Topic created.\n";
} catch (MnsException $e) {
    echo "Failed to create topic: " . $e . "\n";
    return;
}

$topic = $client->getTopicRef($topicName);

Step 2: Create a queue for receiving messages

Create a queue that acts as the subscription endpoint. When messages are published to the topic, SMQ pushes them to this queue.

$queueName = "MyQueueExample";
$request = new CreateQueueRequest($queueName);

try {
    $res = $client->createQueue($request);
    echo "Queue created.\n";
} catch (MnsException $e) {
    echo "Failed to create queue: " . $e . "\n";
    return;
}

$queue = $client->getQueueRef($queueName);

Step 3: Subscribe the queue to the topic

Link the queue to the topic by creating a subscription. The BACKOFF_RETRY strategy retries failed deliveries with exponential backoff. The SIMPLIFIED notify content format sends only the message body without metadata wrappers.

$subscriptionName = "MySubscriptionExample";
$attributes = new SubscriptionAttributes(
    $subscriptionName,
    $topic->generateQueueEndpoint($queueName),  // Generate the queue endpoint URL
    'BACKOFF_RETRY',   // Retry policy
    'SIMPLIFIED'       // Notify content format
);

try {
    $topic->subscribe($attributes);
    echo "Subscription created.\n";
} catch (MnsException $e) {
    echo "Failed to subscribe: " . $e . "\n";
    return;
}

Step 4: Publish messages

Publish a raw message

Use PublishMessageRequest to send a plain-text message without encoding:

$messageBody = "test";
$request = new PublishMessageRequest($messageBody);

try {
    $res = $topic->publishMessage($request);
    echo "Raw message published.\n";
} catch (MnsException $e) {
    echo "Failed to publish raw message: " . $e . "\n";
    return;
}

Publish a Base64-encoded message

Use PublishBase64MessageRequest to send a Base64-encoded message. The SDK handles encoding automatically.

For more information about encoding options, see Encode a message body.

$messageBody = "test";
$request = new PublishBase64MessageRequest($messageBody);

try {
    $res = $topic->publishMessage($request);
    echo "Base64-encoded message published.\n";
} catch (MnsException $e) {
    echo "Failed to publish Base64-encoded message: " . $e . "\n";
    return;
}

Step 5: Receive messages from the queue

Poll the queue to retrieve messages pushed from the topic. After processing each message, delete it from the queue to prevent redelivery.

If the published messages were Base64-encoded, decode them on the receiving side.

while (true) {
    try {
        $res = $queue->receiveMessage(3);  // Wait up to 3 seconds for a message
        echo "Message received: " . $res->getMessageBody() . "\n";

        // Delete the message after processing
        $receiptHandle = $res->getReceiptHandle();
        $queue->deleteMessage($receiptHandle);
        echo "Message deleted.\n";
        break;
    } catch (MessageNotExistException $e) {
        // No message available yet. Retry.
        echo "No new messages. Retrying...\n";
    } catch (MnsException $e) {
        echo "Failed to receive message: " . $e . "\n";
        break;
    }
}

Step 6: Clean up resources

After you finish, remove the subscription, topic, and queue to avoid unnecessary charges.

// Unsubscribe
try {
    $topic->unsubscribe($subscriptionName);
    echo "Unsubscribed.\n";
} catch (MnsException $e) {
    echo "Failed to unsubscribe: " . $e . "\n";
    return;
}

// Delete the topic
try {
    $client->deleteTopic($topicName);
    echo "Topic deleted.\n";
} catch (MnsException $e) {
    echo "Failed to delete topic: " . $e . "\n";
    return;
}

// Delete the queue
try {
    $client->deleteQueue($queueName);
    echo "Queue deleted.\n";
} catch (MnsException $e) {
    echo "Failed to delete queue: " . $e . "\n";
    return;
}

What's next