Constants

BASE_DIR

« More »

Classes, interfaces and traits

Connection

Satori RTM Connection.

Access the RTM Service on the connection level to connect to the RTM Service, send and receive PDUs Uses WebSocket client to connect to RTM.

Does not handle any possible exceptions from the WS client.

« More »

Observable

Observable class.

Allows to extend any struct with ability to Fire events and ability to listen for any events.

« More »

RtmClient

RTM client.

The RtmClient class is the main entry point to manage the WebSocket connection from the PHP SDK to RTM.

Use the RtmClient class to create a client instance from which you can publish messages and subscribe to channels, create separate Subscription objects for each channel to which you want to subscribe.

RtmClient has a single-threaded model. This model imposes some limitations:

  • You cannot read from a WebSocket connection and write to it in the same time;
  • You MUST TO read from a WebSocket connection from time to time to avoid buffer overflowing;

Events

RTM Client allows to use Event-Based model for Events. Use client.on<Event> function to continuously processing events.

Base syntax: $client->onEvent($callback_function);

Example:

<?php
$client = new RtmClient(ENDPOINT, APP_KEY);
$client->onConnected(function () {
    echo 'Connected to Satori RTM and authenticated as ' . ROLE . PHP_EOL;
})->onError(function ($type, $error) {
    echo "Type: $type; Error: $error[message] ($error[code])" . PHP_EOL;
});
$client->connect();

Each event handler returns $client object, so you can register callbacks continuously.

You can register multiple callbacks on the same event:

$client = new RtmClient(ENDPOINT, APP_KEY);
$client->onConnected(function () {
     echo 'Callback 1';
});
$client->onConnected(function () {
     echo 'Callback 2';
});
$client->connect();

There are 4 base events:

  • CONNECTED occurs when client is connected to the endpoint
  • DISCONNECTED occurs when client lost connection
  • AUTHENTICATED occurs after successfull authentication
  • ERROR occurs on each error

Event Parametes

onConnected()

  • not passed

onDisconnected($code, $message)

  • int $code TCP socket error codes or internal application code
  • string $message Disconnect reason

onAuthenticated()

  • not passed

onError($type, $error)

  • ERROR_TYPE_APPLICATION|ERROR_TYPE_CONNECTION|ERROR_TYPE_AUTHENTICATION $type Error type
  • array $error Error details. Keys:
    • int $code Error code
    • string $message Error description

Authentication

You can specify role to get role-based permissions (E.g. get an access to Subscribe/Publish to some channels) when connecting to the endpoint. Follow the link to get more information: https://www.satori.com/docs/using-satori/authentication

Use \RtmClient\Auth\RoleAuth to authenticate using role-based authentication:

$options = array(
    'auth' => new RtmClient\Auth\RoleAuth(ROLE, ROLE_SECRET_KEY),
);
$client = new RtmClient(ENDPOINT, APP_KEY, $options);

Subscriptions

RTM client allows to subscribe to channels:

$client->subscribe('animals', function ($ctx, $type, $data) {
     print_r($data);
});

Check the \RtmClient\Subscription\Subscription class to get more information about the possible options.

A subscription callback is called when the following subscription events occur:

SUBSCRIBED - after getting confirmation from Satori RTM about subscription
UNSUBSCRIBED - after successful unsubscribing
DATA - when getting rtm/subscription/data from Satori RTM
INFO - when getting rtm/subscription/info message
ERROR - on every rtm/subscription/error or rtm/subscribe/error

You should specify callback when creating a new subscription. Example:

use RtmClient\Subscription\Events;

$callback = function ($ctx, $type, $data) {
    switch ($type) {
        case Events::SUBSCRIBED:
            echo 'Subscribed to: ' . $ctx['subscription']->getSubscriptionId() . PHP_EOL;
            break;
        case Events::UNSUBSCRIBED:
            echo 'Unsubscribed from: ' . $ctx['subscription']->getSubscriptionId() . PHP_EOL;
            break;
        case Events::DATA:
            foreach ($data['messages'] as $message) {
                if (isset($message['who']) && isset($message['where'])) {
                    echo 'Got animal ' . $message['who'] . ': ' . json_encode($message['where']) . PHP_EOL;
                } else {
                    echo 'Got message: ' . json_encode($message) . PHP_EOL;
                }
            }
            break;
        case Events::ERROR:
            echo 'Subscription failed. ' . $err['error'] . ': ' . $err['reason'] . PHP_EOL;
            break;
    }
};
$subscription = $client->subscribe('animals', $callback, array(
    'filter' => "SELECT * FROM `animals` WHERE who = 'zebra'",
));

Read/Write workflow

Because of RtmClient has a single-threaded model you should alternate read and write operations

Simple publish with ack example. We publish message and require acknowledge from Sator RTM:

$client = new RtmClient(ENDPOINT, APP_KEY);
$client->publish(CHANNEL, 'test message', function ($ack) {
     echo 'Got ack from Satori RTM';
});
$client->tcpReadSync(); // Wait for reply from Satori RTM

In case if you do not want to wait too much time on reading use timeout:

$client = new RtmClient(ENDPOINT, APP_KEY);
$client->publish(CHANNEL, 'test message', function ($ack) {
     echo 'Got ack from Satori RTM';
});
$client->tcpReadSync(2); // Wait for incoming message for 2 seconds only

If you await multiple replies use \RtmClient\RtmClient::waitAllReplies()

$client = new RtmClient(ENDPOINT, APP_KEY);
$client->publish(CHANNEL, 'message', function ($ack) {
     echo 'Got ack 1 from Satori RTM';
});
$client->publish(CHANNEL, 'message-2', function ($ack) {
     echo 'Got ack 2 from Satori RTM';
});
$client->read(CHANNEL, function ($data) {
     echo 'Got read data from Satori RTM';
});
$client->waitAllReplies(); // Also you can specify wait timeout in seconds
echo 'Done!';

// Output:
// Got ack 1 from Satori RTM
// Got ack 2 from Satori RTM
// Got read data from Satori RTM
// Done!

Also there is an Async mode. Reading in this mode means, that you will not be blocked if there are no incoming messages in socket:

use RtmClient\WebSocket\ReturnCode as RC;

$client = new RtmClient(ENDPOINT, APP_KEY);
$client->publish(CHANNEL, 'test message', function ($ack) {
     echo 'Got ack from Satori RTM';
});
$code = $client->tcpReadAsync();
switch ($code) {
 case RC::READ_OK:
     echo 'Read incoming message';
     break;
 case RC::READ_WOULD_BLOCK:
     echo 'There are no messages in socket at this moment';
     break;
 default:
     echo 'Another return code';
}

If you subscribe to the channels and want to publish messages in the same time you can use tcpReadAsync or Async helpers: \RtmClient\RtmClient::sockReadIncoming() or \RtmClient\RtmClient::sockReadFor()

$messages_count = 0;
$client = new RtmClient(ENDPOINT, APP_KEY);
$client->subscribe(CHANNEL, function ($ctx, $type, $data) use (&$messages_count) {
    if ($type == Events::DATA) {
        foreach ($data['messages'] as $message) {
            echo 'Got message: ' . json_encode($message) . PHP_EOL;
            $messages_count++;
        }
    }
});

while (true) {
     $client->sockReadFor(2); // Read possible messages for 2 seconds
     $client->publish(ANOTHER_CHANNEL, time(), function() {
         echo 'Sent time' . PHP_EOL;
     });
     $client->publish(MY_STAT_CHANNEL, $messages_count, function() {
         echo 'Sent messages count' . PHP_EOL;
     });
}

Reconnects

An RtmClient instance is a one-time connection. It means that you cannot continue using client after connection is dropped.

To make a new connection to Satori RTM you can clone previous client:

$new_client = clone $old_client;
$new_client->connect();

All your callbacks will be moved to the new client. After calling connect client will establish a new connection to Satori RTM. Note that you need to restore your subscriptions manually.

See reconnects examples.

« More »

RtmEvents

RTM events list.

« More »

Classes, interfaces and traits

Events

Subscription events list.

« More »

Subscription

RTM Subscription model.

« More »

Classes, interfaces and traits

iAuth

Authentication interface.

« More »

RoleAuth

RTM role-based authentication.

Client connection to RTM is established in default role. Client can acquire different the permissions by authenticating for a different role. This is done in a two-step process using the Handshake and then Authenticate PDU.

« More »

Classes, interfaces and traits

ApplicationException

Application issues exception.

« More »

AuthenticationException

Auth errors exception.

« More »

Classes, interfaces and traits

Client

WebSocket client implementation.

« More »

ReturnCode

List of possible result of read and write operations.

« More »

Classes, interfaces and traits

BadSchemeException

URL bad schema exception.

« More »

ConnectionException

All connection issues exception.

« More »

TimeoutException

Socket read timeout exception.

« More »

Classes, interfaces and traits

LogLevel

Default PSR-3 LogLevels.

« More »

Classes, interfaces and traits

Helper

Helper functions to work with PDU.

« More »

Pdu

Protocol Data Unit (PDU).

« More »

ReturnCode

Code number representation.

« More »