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

Faye Client Laravel Package

nc/faye-client

A Laravel client for the Faye real-time messaging server, making it easy to publish events and subscribe to channels from PHP applications. Integrates Faye/Bayeux pub-sub into Laravel apps for live updates and notifications.

View on GitHub
Deep Wiki
Context7

Getting Started

nc/faye-client is a thin server-side publisher for a Faye Bayeux server. It does not subscribe, long-poll, or manage websockets from PHP — those belong in the browser JS client. PHP’s job is to POST a message to Faye’s /faye endpoint so the Node processes can fan it out.

1. Install

composer require nc/faye-client

The package is from 2014 and pulls an old HTTP adapter (Buzz in most releases). If Composer refuses on a modern Laravel, check the adapter constraint before assuming the package itself is broken.

2. Run a Faye server. Nothing in this package starts Faye; you need a Node process:

// faye-server.js
const faye = require('faye');
const server = new faye.NodeAdapter({ mount: '/faye', timeout: 45 });
server.listen(8000);

3. First publish. In php artisan tinker (or a route you’ll delete afterwards), confirm connectivity end to end:

use Nc\FayeClient\Client;
use Nc\FayeClient\Adapter\BuzzAdapter;
use Buzz\Browser;

$faye = new Client(new BuzzAdapter(new Browser()), 'http://localhost:8000/faye');

$faye->publish('/demo', ['message' => 'hello from Laravel']);

Then subscribe in the browser console on any page that loads faye-browser.js:

const client = new Faye.Client('http://localhost:8000/faye');
client.subscribe('/demo', msg => console.log(msg));

Where to look first

  • vendor/nc/faye-client/README.md and src/Nc/FayeClient/ — confirm the exact constructor signature and which adapters ship with your installed version (they changed between tags).
  • The adapter class (Adapter/BuzzAdapter, etc.) — that is where the HTTP call and error handling actually live.

First real use case: publish from a Laravel event listener after a model is created, so a browser dashboard updates without polling.

Implementation Patterns

Bind the client once. Don’t construct it per call; wrap it in a singleton and keep the endpoint in config/services.php so config:cache works.

// app/Providers/FayeServiceProvider.php
public function register(): void
{
    $this->app->singleton(Client::class, function () {
        return new Client(
            new BuzzAdapter(new Browser()),
            config('services.faye.endpoint') // e.g. http://localhost:8000/faye
        );
    });
}

Wrap it in your own service. The package gives you publish($channel, $data); your app should speak in domain terms, not Bayeux terms.

class FayePublisher
{
    public function __construct(private Client $faye) {}

    public function toUser(int $userId, string $event, array $payload = []): void
    {
        $this->faye->publish("/users/{$userId}", [
            'event'   => $event,
            'payload' => $payload,
        ]);
    }
}

Publish from event listeners, not controllers. Laravel events already give you a natural seam, and listeners are trivially queued.

class PublishOrderShipped
{
    public function handle(OrderShipped $event): void
    {
        app(FayePublisher::class)->toUser(
            $event->order->user_id,
            'order.shipped',
            ['order_id' => $event->order->id]
        );
    }
}

Queue the publish. A dead or slow Faye server should never block a web request. Implement ShouldQueue on the listener (or call the publisher from a job) and set retry/backoff; a publish failure is usually safe to retry.

Use a custom broadcaster on Laravel 5.1+. If you already use broadcast() / Broadcast::event(), don’t bypass it — register a Faye driver so your controllers and events stay broadcaster-agnostic:

class FayeBroadcaster extends Broadcaster
{
    public function __construct(private Client $faye) {}

    public function broadcast(array $channels, $event, array $payload = []): void
    {
        foreach ($channels as $channel) {
            $this->faye->publish('/'.$channel, [
                'event'   => $event,
                'payload' => $payload,
            ]);
        }
    }

    public function auth($request) {}
    public function validAuthenticationResponse($request, $result) {}
}

Register it in BroadcastServiceProvider via Broadcast::extend('faye', ...), and drive it with BROADCAST_DRIVER=faye.

Channel conventions matter. Use hierarchical paths (/users/42, /orders/42/status) so the JS side can wildcard-subscribe (/orders/*) and you keep access rules understandable. Prefix everything with / — Faye silently ignores or errors on channels that don’t start with one, depending on version.

Test by faking the adapter, not the network. Because the client depends on an adapter interface, you can bind a spy in tests and assert your listener published to the right channel with the right payload. This is the main reason to keep the client behind your own FayePublisher rather than calling Client directly in listeners.

Gotchas and Tips

  • The package is unmaintained (last release 2014). Its HTTP dependency (buzz) is ancient and will likely collide with modern Laravel/Guzzle constraints. Expect to either pin an old dependency tree, fork the client, or replace it with a three-line Http::asForm()->post(...) call. Faye’s publish endpoint is simple enough that the package mostly saves you a JSON shape.
  • PHP 7/8 compatibility is on you. Test on the PHP version you actually deploy. If it breaks on PHP 8, it is usually a type-hint/signature issue in the adapter, not the Bayeux logic.
  • Endpoint path must include the mount. If Faye is mounted at /faye, the URL must be http://host:port/faye. A trailing slash or / mismatch produces 404s that look like auth failures.
  • It is publish-only. There is no subscription, handshake, or clientId management. If you need authenticated or stateful Bayeux sessions, this package won’t help; keep auth/extension logic on the Faye server and out of PHP.
  • Failures can be silent. Faye sometimes returns HTTP 200 with a Bayeux error array in the body ([{"error":"..."}]). Log the response body during rollout; do not assume publish() throwing means success and returning means delivery.
  • The HTTP call is synchronous. Even though the code is short, it blocks until the Faye server responds. Always publish from queues on request paths; otherwise a stalled Faye process takes your web tier down with it.
  • Don’t expose Faye’s publish endpoint publicly. Server-to-server publishing means the Faye port should be firewalled to your app servers, and client subscriptions should require a token via a Faye extension. Laravel’s auth is not involved here.
  • Config caching / env. Keep the endpoint in config/services.php under a faye key and reference it with config(). Never read env('FAYE_ENDPOINT') inside the service provider — it returns null after config:cache.
  • Message size and JSON. Faye is fine with reasonable payloads but is not a job queue. Publish identifiers and event names, not serialized Eloquent models. Make sure payloads are JSON-serializable (DateTime needs formatting; resources will throw).
  • Debugging checklist, in order: (1) curl the /faye endpoint directly, (2) check the Faye Node console for the incoming channel, (3) check the browser is subscribed to the exact same path including leading /, (4) check for a reverse proxy stripping POST bodies.
  • Extension points are deliberately small. Swapping the HTTP adapter is the intended customization seam. If you need retries, timeouts, or interceptors, implement them in a decorator around Client (or your FayePublisher) rather than patching the vendor code.
  • Have an exit plan. For most Laravel apps today, a custom Broadcast driver built on Illuminate\Support\Facades\Http or Redis pub/sub is more maintainable than this package. Keep FayePublisher as the abstraction so the eventual swap is one class, not a search-and-replace.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings