Skip to main content
Markdown

PHP reference: wordplus/realtime-php

The package needs PHP 8.1 or later, with sodium, and curl or PHP's streams. It takes the same options as the Node and Python packages, and answers the browser the same way. In Laravel, the Realtime facade and app( Realtime::class ) are one instance, made from config/wordplus-realtime.php (Laravel).

new Realtime( $options )​

Realtime::fromEnvironment( $options ) is the same, with site, secret and local_key taken from WORDPLUS_SITE, WORDPLUS_SECRET and WORDPLUS_LOCAL_KEY.

Option
site, secretyour app's key and secret
local_key64 hex characters of your own (encryption)
profilefn ( $user ) => [ 'name' => …, 'avatar' => …, 'url' => … ] or null: the user's directory entry, and by default their presence info and call info
has_keysfn ( $user ) => false cuts a user off every key
generationsa GenerationStore, for rotateChannel() and rotateUser()
sealfalse sends everything plain
basewhere your routes are, /api/realtime by default, for config()
headersheaders the browser sends to your routes, such as a CSRF token, for config()
worker, roomswhere your app serves the two files, for config()
token_ttl, call_token_ttlseconds: 6 hours by default; a channels token lasts at most a day, a calls token at most 6 hours
server, apiWordPlus Cloud by default
httpfn ( $method, $url, $headers, $body ) => [ 'status' => …, 'body' => … ], your own client for publishing

A user is the id your app gives, an integer or a string, or null for nobody. In this version, calls and the directory take integer ids only.

Owners​

Method
channel( $prefix, fn ( $user, $channel ) => $answer )private and presence channels, by the start of their names; answers false, true, or [ 'id' => …, 'info' => … ] (channels, presence)
calls( $prefix, fn ( $user, $call, $with ) => $answer )calls and rooms; answers false, true, or [ 'info', 'publish', 'subscribe', 'admin', 'hidden' ] (calls)
kind( $kind, fn ( $rest, $user, $label ) => bool, $newest = null )keys of your own kind (encryption)
fallback( fn ( $user, $channel ) => $answer )the channels no prefix owns; in Laravel, routes/channels.php

The longest prefix that fits decides. Each method returns the instance, so calls chain.

Routes​

Method
respond( $action, $user )answers the current request in plain PHP: auth, calls or keys, with its status, headers and JSON
answerRequest( $method, $contentType, $action, $body, $user )→ [ 'status', 'body' ], for a framework of your own
handle( $action, $body, $user )→ [ 'status', 'body' ], for a body already decoded

The routes take JSON POSTs only, and answer anything else with 415. A page on another site can't send JSON without asking first, and it is never allowed to. A refusal is part of the answer (denied), not an HTTP error.

MethodWhat it answers
authorize( $channels, $user )[ 'token', 'exp', 'keys', 'denied' ]
authorizeCall( $request, $user )[ 'token', 'exp', 'key' ] or [ 'denied' => … ]
keysAnswer( $labels, $user )[ 'keys', 'identity'? ]
identity( $user )[ 'token', 'exp' ] or null
token( $channels, $user = null, $info = null, $ttl = null )a channels token, signed as the auth route signs
config( $user = null, $headers = [] )the browser's settings for connect(), with a signed-in user's keys and identity
mayJoin( $channel, $user ), mayHave( $label, $user )what the routes decide, for your own checks

Publishing​

Method
publish( $channels, $event, $data = null, [ 'except' => $tab, 'seal' => false ] )one channel, or up to 100; data up to 10 KB of JSON (publishing)
publishBatch( [ [ 'channels', 'event', 'data', 'except', 'seal' ], … ] )10 events a request
channelInfo( $channel )[ 'subscriptions', 'members'? ]
rotateChannel( $channel ), rotateUser( $user )moves a key on; needs generations

They throw RealtimeError when WordPlus Cloud refuses: $e->errorCode holds the code, and $e->status the HTTP status.

Keys​

$realtime->keys() is the app's Keys:

Method
seal( $text, $label ), sealJson( $data, $label )a sealed value, {label}:1.{…}
open( $value )the text, or null
entry( $label )a key as the browser takes it
dayLabel(), channelLabel( $channel ), userLabel( $user )the labels the SDK uses

Generations​

interface GenerationStore
{
public function get( string $name ): ?int;
public function set( string $name, int $generation ): void;
}

Keep them where all your servers see them, and for good: a database row, or a cache that doesn't evict. In Laravel, WordPlus\Realtime\Laravel\CacheGenerations keeps them in a cache store.

Helpers​

Realtime::channelKind( $channel ) gives public, private or presence. Realtime::validChannel( $channel ) says whether WordPlus Cloud takes the name.