Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Centrifugo Laravel Package

oleh-ozimok/php-centrifugo

A PHP client for Centrifugo, the scalable real-time messaging server. Publish messages to channels via the HTTP API, push live updates to websocket clients, and integrate real-time features into Laravel or any PHP application with a simple, framework-agnostic interface.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package

    composer require oleh-ozimok/php-centrifugo
    

    There is no Laravel auto-discovery service provider — this is a framework-agnostic library. Confirm the actual namespace/class name by listing the package source, e.g. ls vendor/oleh-ozimok/php-centrifugo/src. Expect something like Ozimok\Centrifugo\Client constructed with an endpoint URL and API key.

  2. Add config in config/services.php so credentials never live in code:

    'centrifugo' => [
        'url'    => env('CENTRIFUGO_URL', 'http://127.0.0.1:8000'),
        'api_key' => env('CENTRIFUGO_API_KEY'),
    ],
    

    And in .env:

    CENTRIFUGO_URL=http://127.0.0.1:8000
    CENTRIFUGO_API_KEY=your-secret-key
    
  3. Bind it as a singleton in App\Providers\AppServiceProvider::register() so you get connection reuse and a single place to swap/mock it:

    $this->app->singleton(\Ozimok\Centrifugo\Client::class, function () {
        return new \Ozimok\Centrifugo\Client(
            config('services.centrifugo.url'),
            config('services.centrifugo.api_key')
        );
    });
    
  4. First use case — publish a change from a controller after a model is saved:

    public function update(Request $request, Post $post, \Ozimok\Centrifugo\Client $centrifugo)
    {
        $post->update($request->validated());
    
        $centrifugo->publish("post.{$post->id}", [
            'event' => 'post.updated',
            'body'  => $post->toArray(),
        ]);
    
        return response()->json($post);
    }
    

If the publish call fails, the first thing to check is whether your Centrifugo server version matches the endpoint/auth scheme this 2018-era client expects (see Gotchas).

Implementation Patterns

Always publish from the server, never the browser. The client is a backend HTTP wrapper around Centrifugo's publish API; the API key must never reach the frontend. Laravel is the trust boundary.

Wrap the library in your own thin service. This keeps the third-party class out of controllers and gives you a stable seam for testing:

namespace App\Services;

class Broadcaster
{
    public function __construct(private \Ozimok\Centrifugo\Client $client) {}

    public function toChannel(string $channel, array $payload): void
    {
        $this->client->publish($channel, $payload);
    }
}

Publish after commit, not inside the transaction. Emitting a real-time event before the DB commits means a client can react to data that later rolls back:

DB::transaction(function () use ($post, $broadcaster) {
    $post->update([...]);
});

$broadcaster->toChannel("post.{$post->id}", ['event' => 'post.updated', 'body' => $post]);

Or push it to a listener on PostUpdated and have that listener implement ShouldQueue/$afterCommit = true.

Prefer queue jobs for fan-out. Publishing in a queued job keeps request latency flat and gives you retries:

class BroadcastPostUpdate implements ShouldQueue
{
    public function __construct(public int $postId) {}

    public function handle(Broadcaster $broadcaster): void
    {
        $post = Post::find($this->postId);
        if (! $post) return;
        $broadcaster->toChannel("post.{$post->id}", ['event' => 'post.updated', 'body' => $post->toArray()]);
    }
}

Broadcast to many channels in one request. The library supports publishing to multiple channels per call — use it for notification fan-out (e.g. all members of a group) instead of looping HTTP calls:

$channels = $group->members->map(fn ($u) => "user.{$u->id}")->all();
$client->publish($channels, ['event' => 'group.mention', 'group' => $group->id]);

Conventional channel naming. Pick a scheme once and stick to it: user.{id} for per-user feeds, post.{id} for resource rooms, private-user.{id} where Centrifugo namespace rules require prefixed channels. Keep the naming logic in one helper so backend and frontend agree.

Testing. Because the library makes real HTTP calls, don’t hit it in tests. Either (a) swap the singleton for a fake in TestCase::setUp() / a Mockery spy, or (b) if the client is Guzzle-based and accepts a client in its constructor, inject a GuzzleHttp\Handler\MockHandler. Faking the concrete class is brittle, which is another reason to depend on App\Services\Broadcaster in production code.

Console/scheduler integration. Nothing special is required — resolve the client via the container inside commands ($this->laravel->make(Client::class)) or type-hint it in handle(). Useful for periodic digests, cache warmers, or a centrifugo:ping health command.

Gotchas and Tips

  • Version skew is the big one. This package last shipped in 2018, when Centrifugo’s HTTP API used POST /api with Authorization: apikey <key> (v1/v2 era). Centrifugo v4/v5 introduced X-API-Key and stricter JSON shape changes. Verify your server version and, if mismatched, either pin the server or skip the library and call the endpoint with Laravel’s Http client. Confirm the class name and method signatures in vendor/ before writing code — READMEs for small 2018 packages are often stale relative to the tagged source.
  • Publish failures are silent-ish. Wrap publish calls in try/catch for transport/HTTP errors and log with channel + event context. Never let a failed publish abort a user request that already succeeded in the database.
  • Timeouts. Set a short timeout on the underlying HTTP transport; a slow Centrifugo should degrade live updates, not hang checkout.
  • Payload limits. Keep payloads small and JSON-serializable. Strip models down (only([...])) rather than sending toArray() of large relations; large payloads hurt every connected client.
  • No offline delivery by default. Centrifugo drops messages for disconnected clients unless history/recovery is enabled server-side. Don’t treat a publish as a delivery guarantee — pair live updates with a fetch-on-reconnect in the frontend.
  • Channel permissions live in Centrifugo, not Laravel. Authorizing who can subscribe happens via Centrifugo’s connect/subscribe proxies or JWT. Building a private- channel in Laravel does nothing unless Centrifugo is configured to enforce it.
  • API key handling. Store it only in .env/secret manager. If it leaks to a JS bundle, anyone can publish to any channel.
  • Extension point. If the constructor accepts an HTTP client/transport, inject a configured Guzzle client (retry middleware, logging middleware, proxy) rather than letting the library create its own. That’s also how you make it testable while staying on the library.
  • Consider a modern alternative if you need Centrifugo v4/v5 features (bidirectional, server-side subscriptions, newer auth). A ~50-line Laravel wrapper around Http::withHeaders(['X-API-Key' => ...])->post("{$url}/api", ['method' => 'publish', ...]) is often easier to maintain than adapting an eight-year-old client — and it plays nicely with Http::fake() in tests.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource