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 »
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
<?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:
```php
$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](../classes/RtmClient.Auth.RoleAuth.html) to authenticate using role-based authentication:
```php
$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](../classes/RtmClient.Subscription.Subscription.html) 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()](../classes/RtmClient.RtmClient.html#method_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()](../classes/RtmClient.RtmClient.html#method_sockReadIncoming) or [\RtmClient\RtmClient::sockReadFor()](../classes/RtmClient.RtmClient.html#method_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 »