roadrunner-php/centrifugo
PHP client for Centrifugo with RoadRunner integration, helping you publish messages and manage real-time channels from your app. Lightweight package aimed at fast, scalable WebSocket/SSE push in PHP services.
Start by installing the package via Composer:
composer require roadrunner-php/centrifugo
The core class is Centrifugo\Client. You’ll instantiate it with your Centrifugo HTTP API credentials and base URL (e.g., http://localhost:8000/api):
use Centrifugo\Client;
$client = new Client(
url: 'http://localhost:8000/api',
apiKey: 'your-centrifugo-api-key',
secret: 'your-centrifugo-secret' // required for signing requests
);
💡 First use case: Push a real-time update to all users subscribed to a channel:
$client->publish('news', ['message' => 'New update!']);
Check the Centrifugo docs to confirm your server is running and the HTTP API is enabled (http_api section in config). Ensure centrifugo is started with proper API access enabled (port 8000 by default).
Use publish() for single-channel updates, ideal for broadcasting events like chat messages, notifications, or live scores:
$client->publish('chat:room-123', [
'user_id' => 42,
'text' => 'Hello world!',
'timestamp' => time()
]);
Use broadcast() to push the same payload to multiple channels — efficient for system-wide announcements:
$client->broadcast([
['channel' => 'alerts:general', 'data' => ['type' => 'maintenance']],
['channel' => 'alerts:support', 'data' => ['type' => 'ticket-created']],
]);
Leverage server-side management methods for debugging or operational workflows:
presence(string $channel) → get channel subscribershistory(string $channel) → get recent messages (if history enabled) unsubscribe(string $channel, string $client) → force client disconnectdisconnect(string $client) → kill a specific client connectionExample: kick a misbehaving client:
$client->disconnect('client-abc123');
Use in Laravel: bind the client as a singleton in a service provider:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(Client::class, function () {
return new Client(
url: config('centrifugo.url'),
apiKey: config('centrifugo.api_key'),
secret: config('centrifugo.secret')
);
});
}
Then inject into jobs, commands, or controllers:
public function store(Request $request, Client $centrifugo)
{
// ... save model
$centrifugo->publish('notifications:user-'.$request->user()->id, [
'message' => 'Your profile was updated',
]);
}
Since this is a RoadRunner bridge, pair it with RoadRunner’s worker processes (e.g., for long-running broadcast services). Avoid publishing inside request cycles for high-volume events — use queues (e.g., spiral/roadrunner-queue) to decouple.
Centrifugo’s HTTP API is sensitive. Always:
apiKey and secret in .env + secure vaultThe client supports HMAC signing — ensure $secret is set. Omitting it will cause 401s on administrative endpoints.
The client uses Guzzle under the hood. Set custom timeouts:
$client = new Client(
url: 'http://centrifugo:8000/api',
apiKey: '...',
secret: '...',
options: ['timeout' => 2.5, 'connect_timeout' => 1.0]
);
Set low timeouts — slow Centrifugo responses shouldn’t block your PHP app.
Centrifugo restricts message size (default: 64 KiB). Avoid sending large binary data. For file updates, send only a signed URL:
$client->publish('files:updated', [
'file_id' => $file->id,
'download_url' => SignedUrl::for($file)->toString()
]);
The client does not auto-retry. Wrap calls in retry logic for critical events (e.g., notification delivery):
$retry = new RetryStrategy(maxAttempts: 3, delayMs: 100);
$retry->execute(fn() => $client->publish('urgent', $payload));
Consider using oneway() for fire-and-forget scenarios where delivery confirmation isn’t needed (avoiding HTTP round-trip overhead).
broadcast() and publish() scale with network I/O, not PHP memory — good for high-load systems/stats) to detect bottlenecksEnable Guzzle debug logs in Laravel by extending the client:
$client = new Client(
url: '...',
apiKey: '...',
secret: '...',
options: [
'handler' => HandlerStack::create(new MiddlewareInspector()),
'debug' => env('APP_DEBUG', false)
]
);
Check Centrifugo logs for http_api errors — most failures show up there with clear messages (e.g., "invalid token" or "channel not allowed").
How can I help you explore Laravel packages today?