PHP SDK - Realtime#

Subscriptions use the SSE transport by default (transport: 'websocket' for the Centrifugo WebSocket). run() blocks, so run it in a long-lived worker process (for example a Laravel artisan command or daemon).

Subscribe#

$sub = $db->realtime->subscribe(
    'messages',
    function (array $event): void {
        // $event['type']       => INSERT | UPDATE | DELETE
        // $event['table']      => messages
        // $event['record']     => the changed row
        // $event['old_record'] => previous row (UPDATE/DELETE)
        echo $event['type'] . ': ' . json_encode($event['record']);
    },
    ['events' => ['INSERT', 'DELETE']], // optional filter
);

$sub->run();      // blocks until close() is called or the stream ends
$sub->close();    // stop (safe from another process via a stop marker)
$sub->stopped();  // bool
PHP

How it works#

  1. SSE reads /projects/{id}/realtime/events?api_key=...&table=... and reconnects every 3 seconds if the stream drops.
  2. WebSocket calls POST /projects/{id}/realtime/connect?table=..., opens the Centrifugo socket and subscribes to the channel, also reconnecting.
  3. close() writes a stop marker that run() polls between frames, so the subscription can be stopped from another process.

Event payload#

{
  "id": "uuid",
  "type": "INSERT",
  "table": "messages",
  "project_id": "5c73dab0-...",
  "record": { "id": "...", "message": "hello" },
  "old_record": null,
  "created_at": "2026-10-03T20:47:34Z"
}
JSON

Next: Storage.