PHP SDK


The official PHP SDK for Togo MQ provides a comprehensive, production-ready client for integrating Togo MQ into your PHP applications.

Installation

Requirements

  • PHP 8.1 or higher
  • gRPC PHP extension
  • Access to a TogoMQ account - Sign up here if you don't have one
  • Valid TogoMQ authentication token - Generate one in your dashboard

Install SDK

Install the SDK using Composer:

composer require togomq/togomq-sdk

Install gRPC Extension

Make sure you have the gRPC PHP extension installed:

pecl install grpc

Verify Installation

Create a simple test file:

<?php

require 'vendor/autoload.php';

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;

// Create client
$config = new Config('test-token');
$client = new Client($config);

echo "TogoMQ SDK installed successfully!\n";

$client->close();

Run: php test_install.php

Quick Start

<?php

require 'vendor/autoload.php';

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;
use TogoMQ\SDK\Message;

// Create client with your token
$config = new Config('your-token-here');
$client = new Client($config);

// Publish a message
$messages = [new Message('orders', 'Hello TogoMQ!')];
$response = $client->pubBatch($messages);

echo "Published {$response->getMessagesReceived()} messages\n";

// Always close the client when done
$client->close();

SDK Features

  • 🚀 High Performance - Built on gRPC for efficient communication
  • 📡 Streaming Support - Native support for streaming pub/sub operations
  • 🔒 Secure - TLS encryption and token-based authentication
  • 🎯 Simple API - Easy-to-use client with fluent configuration
  • 📝 Comprehensive Logging - Configurable log levels for debugging
  • Modern PHP - Requires PHP 8.1+ with strict typing
  • Well Tested - Comprehensive test coverage

Configuration

The SDK supports flexible configuration with sensible defaults. You only need to provide your authentication token to get started.

Default Configuration

<?php

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;

// Create client with defaults (only token is required)
$config = new Config('your-token-here');
$client = new Client($config);

Default values:

  • Host: q.togomq.io
  • Port: 5123
  • LogLevel: info
  • Token: (required - no default)

Configuration Options

Option Default Value Description
Host q.togomq.io TogoMQ server hostname
Port 5123 TogoMQ server port
LogLevel info Logging level: debug, info, warn, error, none
Token (required) Authentication token from your dashboard

Custom Configuration

Use fluent interface for custom configuration:

<?php

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;

$config = (new Config('your-token-here'))
    ->withHost('custom.togomq.io')
    ->withPort(9000)
    ->withLogLevel('debug');

$client = new Client($config);

Environment-Based Configuration

Development:

<?php

$config = (new Config(getenv('TOGOMQ_DEV_TOKEN')))
    ->withLogLevel('debug'); // Verbose logging

Production:

<?php

$config = (new Config(getenv('TOGOMQ_PROD_TOKEN')))
    ->withLogLevel('error'); // Only log errors

Publishing Messages

Togo MQ provides flexible methods for publishing messages using batch operations.

{danger} Important: The topic name is required for all published messages.

Message Structure

<?php

use TogoMQ\SDK\Message;

$message = new Message(
    topic: 'orders',           // Message topic (required)
    body: 'Message payload'    // Message payload
);

// Optional properties (fluent interface)
$message
    ->withVariables(['key' => 'value'])  // Custom metadata
    ->withPostpone(60)                   // Delay in seconds
    ->withRetention(3600);               // Keep for 1 hour

Publishing a Batch of Messages

<?php

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;
use TogoMQ\SDK\Message;

// Create client
$config = new Config('your-token');
$client = new Client($config);

// Create messages - topic is required for each message
$messages = [
    new Message('orders', 'order-1'),
    (new Message('orders', 'order-2'))
        ->withVariables([
            'priority' => 'high',
            'customer' => '12345',
        ]),
    (new Message('orders', 'order-3'))
        ->withPostpone(60)      // Delay 60 seconds
        ->withRetention(3600),  // Keep for 1 hour
];

// Publish
$response = $client->pubBatch($messages);

echo "Published {$response->getMessagesReceived()} messages\n";

// Always close the client when done
$client->close();

Message Options

Custom Metadata:

<?php

$message = (new Message('orders', 'order-data'))
    ->withVariables([
        'order_id' => '12345',
        'customer_id' => '98765',
        'priority' => 'high',
        'region' => 'us-east',
    ]);

Delayed Messages:

<?php

// Delay 60 seconds
$message = (new Message('reminders', 'Send email'))
    ->withPostpone(60);

// Delay 1 hour
$message = (new Message('scheduled-tasks', 'Run backup'))
    ->withPostpone(3600);

Message Retention:

<?php

// Keep for 1 hour
$message = (new Message('temporary-events', 'data'))
    ->withRetention(3600);

Best Practices

1. Reuse Clients:

<?php

// Good ✅
$client = new Client($config);

for ($i = 0; $i < 1000; $i++) {
    $client->pubBatch($messages);
}

$client->close();

2. Batch Publishing:

<?php

// Good ✅
$messages = [$msg1, $msg2, $msg3];
$client->pubBatch($messages);

3. Handle Errors:

<?php

use TogoMQ\SDK\Exception\TogoMQException;

try {
    $response = $client->pubBatch($messages);
} catch (TogoMQException $e) {
    switch ($e->getErrorCode()) {
        case TogoMQException::ERR_CODE_AUTH:
            echo "Authentication failed\n";
            break;
        case TogoMQException::ERR_CODE_CONNECTION:
            echo "Connection error\n";
            break;
    }
}

Subscribing to Messages

Subscribe to messages published to specific topics using an iterator-based approach.

{danger} Important: Topic is required. Use wildcards like "orders.*" or "*" for all topics.

Received Message Structure

<?php

// When receiving messages, they include:
$topic = $message->getTopic();              // Message topic
$uuid = $message->getUuid();                // Unique message identifier
$body = $message->getBody();                // Message payload
$variables = $message->getVariables();      // Custom metadata array
$value = $message->getVariable('key');      // Get specific variable

Basic Subscription

<?php

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;
use TogoMQ\SDK\SubscribeOptions;

// Create client
$config = new Config('your-token');
$client = new Client($config);

// Subscribe to specific topic (topic is required)
// Use "*" to subscribe to all topics
$options = new SubscribeOptions('orders');
$subscription = $client->sub($options);

// Receive messages
foreach ($subscription as $message) {
    echo "Received from {$message->getTopic()}: {$message->getBody()}\n";
    echo "UUID: {$message->getUuid()}\n";

    // Access variables
    $priority = $message->getVariable('priority');
    if ($priority !== null) {
        echo "Priority: {$priority}\n";
    }
}

$client->close();

Advanced Subscription Options

Batch Size - Control messages received at once:

<?php

$options = (new SubscribeOptions('orders'))
    ->withBatch(10);

Rate Limiting - Limit messages per second:

<?php

$options = (new SubscribeOptions('orders'))
    ->withSpeedPerSec(100);

Combined Options:

<?php

// Default: Batch = 0 (server default 1000), SpeedPerSec = 0 (unlimited)
$options = (new SubscribeOptions('orders.*'))  // Wildcard topic
    ->withBatch(10)                             // Receive up to 10 messages
    ->withSpeedPerSec(100);                     // Limit to 100 msgs/sec

$subscription = $client->sub($options);

foreach ($subscription as $message) {
    processMessage($message);
}

Wildcard Subscriptions

All topics:

<?php

// Subscribe to all topics using "*" wildcard
$options = new SubscribeOptions('*'); // "*" = all topics
$subscription = $client->sub($options);

Pattern matching:

<?php

// All order topics (orders.new, orders.updated, etc.)
$options = new SubscribeOptions('orders.*');
$subscription = $client->sub($options);

// All critical events
$options = new SubscribeOptions('*.critical');
$subscription = $client->sub($options);

Subscription with Error Handling

<?php

use TogoMQ\SDK\Exception\TogoMQException;

try {
    $options = new SubscribeOptions('events');
    $subscription = $client->sub($options);

    foreach ($subscription as $message) {
        processMessage($message);
    }
} catch (TogoMQException $e) {
    echo "Subscription error ({$e->getErrorCode()}): {$e->getMessage()}\n";
}

Best Practices

1. Always Close Connections:

<?php

$client = new Client($config);

try {
    $subscription = $client->sub($options);
    foreach ($subscription as $message) {
        processMessage($message);
    }
} finally {
    $client->close();
}

2. Handle Errors Gracefully:

<?php

try {
    foreach ($subscription as $message) {
        try {
            processMessage($message);
        } catch (\Exception $e) {
            echo "Failed to process {$message->getUuid()}: {$e->getMessage()}\n";
        }
    }
} catch (TogoMQException $e) {
    echo "Subscription error: {$e->getMessage()}\n";
}

Error Handling

The SDK provides detailed error information for graceful failure handling and debugging.

Error Structure

<?php

use TogoMQ\SDK\Exception\TogoMQException;

try {
    $response = $client->pubBatch($messages);
} catch (TogoMQException $e) {
    // Check error type
    echo "Error code: {$e->getErrorCode()}\n";
    echo "Error message: {$e->getMessage()}\n";
}

Error Codes

Error Code Description Common Causes
ERR_CODE_CONNECTION Connection/network errors Network issues, firewall, DNS
ERR_CODE_AUTH Authentication failures Invalid/expired/revoked token
ERR_CODE_VALIDATION Invalid input/config Missing topic, invalid data
ERR_CODE_PUBLISH Publishing errors Server-side failures
ERR_CODE_SUBSCRIBE Subscription errors Server-side failures
ERR_CODE_STREAM Streaming errors Stream interrupted
ERR_CODE_CONFIGURATION Config errors Invalid host/port

Handling Errors

Basic:

<?php

try {
    $response = $client->pubBatch($messages);
} catch (TogoMQException $e) {
    echo "Failed: {$e->getMessage()}\n";
}

Detailed:

<?php

use TogoMQ\SDK\Exception\TogoMQException;

try {
    $response = $client->pubBatch($messages);
} catch (TogoMQException $e) {
    switch ($e->getErrorCode()) {
        case TogoMQException::ERR_CODE_AUTH:
            echo "Authentication failed - check token\n";
            break;
        case TogoMQException::ERR_CODE_CONNECTION:
            echo "Connection error - will retry\n";
            break;
        case TogoMQException::ERR_CODE_VALIDATION:
            echo "Validation error: {$e->getMessage()}\n";
            break;
        default:
            echo "Error ({$e->getErrorCode()}): {$e->getMessage()}\n";
    }
}

Retry Logic

<?php

function publishWithRetry(Client $client, array $messages, int $maxRetries = 3) {
    for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
        try {
            return $client->pubBatch($messages);
        } catch (TogoMQException $e) {
            // Don't retry auth/validation errors
            if (in_array($e->getErrorCode(), [
                TogoMQException::ERR_CODE_AUTH,
                TogoMQException::ERR_CODE_VALIDATION
            ])) {
                throw $e;
            }

            if ($attempt < $maxRetries - 1) {
                $backoff = 2 ** $attempt;
                echo "Retry " . ($attempt + 1) . " after {$backoff}s\n";
                sleep($backoff);
            } else {
                throw $e;
            }
        }
    }
}

Best Practices

1. Reuse Clients

Create one client per application and reuse it:

<?php

// Good ✅
$client = new Client($config);

for ($i = 0; $i < 1000; $i++) {
    $client->pubBatch($messages);
}

$client->close();

2. Always Close Connections

<?php

$client = new Client($config);

try {
    $client->pubBatch($messages);
} finally {
    $client->close();
}

3. Handle Errors

<?php

try {
    $response = $client->pubBatch($messages);
    echo "Published {$response->getMessagesReceived()} messages\n";
} catch (TogoMQException $e) {
    echo "Error: {$e->getMessage()}\n";
}

4. Batch Messages

Use pubBatch() for better performance:

<?php

// Good ✅
$messages = [$msg1, $msg2, $msg3];
$client->pubBatch($messages);

5. Validate Topics

Always provide valid topic names:

<?php

// Good ✅
$message = new Message('orders', 'data');

// Bad ❌
$message = new Message('', 'data'); // Empty topic will fail

6. Set Log Levels

Control logging based on environment:

<?php

// Development
$config = (new Config($token))->withLogLevel('debug');

// Production
$config = (new Config($token))->withLogLevel('error');

Complete Examples

Publishing Example

<?php

require 'vendor/autoload.php';

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;
use TogoMQ\SDK\Message;

// Create client
$config = new Config(getenv('TOGOMQ_TOKEN'));
$client = new Client($config);

try {
    // Create messages
    $messages = [];
    for ($i = 0; $i < 100; $i++) {
        $message = (new Message('events', "event-{$i}"))
            ->withVariables([
                'index' => (string)$i,
                'type' => 'test'
            ]);
        $messages[] = $message;
    }

    // Publish batch
    $response = $client->pubBatch($messages);
    echo "Published {$response->getMessagesReceived()} messages\n";

} catch (\Exception $e) {
    echo "Error: {$e->getMessage()}\n";
} finally {
    $client->close();
}

Subscribing Example

<?php

require 'vendor/autoload.php';

use TogoMQ\SDK\Config;
use TogoMQ\SDK\Client;
use TogoMQ\SDK\SubscribeOptions;
use TogoMQ\SDK\Exception\TogoMQException;

// Graceful shutdown handler
$shutdown = false;
pcntl_signal(SIGINT, function() use (&$shutdown) {
    echo "\nShutting down gracefully...\n";
    $shutdown = true;
});

// Create client
$config = new Config(getenv('TOGOMQ_TOKEN'));
$client = new Client($config);

try {
    // Subscribe with options
    $options = (new SubscribeOptions('orders.*'))
        ->withBatch(10)
        ->withSpeedPerSec(100);

    $subscription = $client->sub($options);

    echo "Subscribed, waiting for messages...\n";

    foreach ($subscription as $message) {
        pcntl_signal_dispatch(); // Handle signals

        if ($shutdown) {
            break;
        }

        echo "[{$message->getUuid()}] {$message->getTopic()}: {$message->getBody()}\n";

        // Process message
        processMessage($message);
    }

} catch (TogoMQException $e) {
    echo "Subscription error: {$e->getMessage()}\n";
} finally {
    $client->close();
}

function processMessage($message) {
    // Your business logic
}

Resources


{success} Check out the FAQ for common questions about Togo MQ.