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

Pusher Bundle Laravel Package

laupifrpar/pusher-bundle

Pusher Bundle integrates Pusher real-time messaging with Laravel, offering configuration and helpers to publish events and subscribe clients to WebSocket channels. It simplifies adding live updates and notifications to PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Before anything else: this is not a Laravel package. laupifrpar/pusher-bundle is a Symfony bundle (Lopi\Bundle\PusherBundle) whose service container registration, bundle class, and Twig extension map to Symfony's Kernel, not a Laravel ServiceProvider. In a Laravel codebase you cannot composer require this and expect it to wire itself up; the practical options are (a) skip it and use pusher/pusher-php-server directly with Laravel's built-in pusher broadcast driver, or (b) treat this bundle as a reference implementation and port the small amount of logic (a service around Pusher\Pusher plus a Blade partial for the client config) into a Laravel service provider.

What changed in 6.1.0: end-to-end encryption support. This is a feature addition, not a breaking change — existing plaintext channel usage keeps working. It matters because it confirms the 6.x line is still actively maintained (the older "last release 2022" read is now stale), and because encryption changes how you configure channels, auth endpoints, and the front-end client. If you are on Symfony, upgrade to 6.1.0 before building any encrypted channel support; the older tags cannot do it.

If you are actually on Symfony (the only place this package fits), the minimal steps are:

  1. composer require laupifrpar/pusher-bundle and register new Lopi\Bundle\PusherBundle\LopiPusherBundle() in your kernel.
  2. Add config keys: lopi_pusher: { app_id, key, secret, options: { cluster: eu } }, plus whatever encryption flag 6.1.0 introduces — check DependencyInjection/Configuration.php on the 6.1.0 tag for the exact node name rather than guessing.
  3. Inspect Services/ for the service id (typically the Pusher\Pusher client under a lopi_pusher alias) and confirm the pusher/pusher-php-server version constraint moved with 6.1.0 — encryption support requires a recent SDK.
  4. First use case: from a controller, grab the service and fire a server-side event to a channel with a JSON payload; then render the front-end Pusher JS with the public key and cluster from config. For encryption, the first use case becomes private-encrypted-orders with the same call.

For Laravel, your "first use case" is the same shape but the setup is: BROADCAST_DRIVER=pusher in .env, PUSHER_APP_ID/KEY/SECRET/CLUSTER, install pusher/pusher-php-server, and either use broadcast(new Event(...)) on a ShouldBroadcast event or inject Pusher\Pusher for direct trigger() calls. Encryption is available to you there too — via Illuminate\Broadcasting\PrivateEncryptedChannel in broadcastOn() — without needing this bundle at all.

Implementation Patterns

Server-side trigger via the container (Symfony). The bundle's whole value proposition is that it wires Pusher\Pusher into the service container using your config, so you don't construct the client yourself:

$pusher = $this->get('lopi_pusher'); // or inject via constructor
$pusher->trigger('orders', 'order.shipped', ['id' => $order->getId()]);

Prefer constructor injection of the service over $this->get() so the dependency is explicit and testable.

Encrypted channels (new in 6.1.0). Encryption in Pusher Channels is opt-in per channel and tied to the channel name prefix: only private-encrypted-* channels are encrypted. Public and presence channels cannot be encrypted — there is no presence-encrypted- and there is no encrypted public channel. So the pattern is:

$pusher->trigger('private-encrypted-orders.'.$order->getId(), 'order.shipped', $payload);

The server SDK handles the payload crypto for you; your job is (a) name the channel correctly, (b) make sure the client subscribes with a JS client that supports decryption, and (c) let the SDK produce the auth response. Do not hand-roll channel authorization: for encrypted channels the auth payload must include a shared_secret field derived from your master key pair, and the SDK's authorizeChannel/socket-auth helpers emit it. A hand-written HMAC auth endpoint that works fine today will silently break the moment you rename a channel to private-encrypted-*.

Front-end bootstrap. The bundle's Twig extension renders the Pusher JS snippet with your key/cluster so you don't hardcode them in templates. In a ported Laravel version, do the same with a Blade partial and config('broadcasting.connections.pusher.key') / config('broadcasting.connections.pusher.options.cluster') — only the key and cluster ever go to the browser, never the secret and never the encryption master key.

Private, presence, and now encrypted channels. The bundle gives you the server client, not an auth endpoint you can rely on. You implement the auth route yourself calling the SDK's auth helpers (authorizeChannel, socket_auth, presence_auth) and return the JSON the Pusher JS client expects. Presence channels additionally need a stable user_id and user_info — derive these from your authenticated user, not from a query param. If you support both encrypted and plaintext private channels, keep two distinct auth code paths and test both; mixing them is the easiest way to ship a channel that silently fails to decrypt in the browser.

Laravel translation of the pattern. Wrap Pusher\Pusher in a small PusherService bound as a singleton in a service provider, so controllers/jobs depend on your interface rather than a concrete SDK. For anything broadcastable, prefer Laravel's ShouldBroadcast events and Echo on the front end; use PrivateEncryptedChannel when the payload is sensitive. Reserve direct trigger() calls for low-level fan-out (batch notifications, cache invalidation signals) where an Eloquent-style event is overkill.

Workflow for teams. Centralize channel naming (private-user.{id}, presence-room.{id}, private-encrypted-order.{id}) in constants or a helper — event-name, channel-name, and prefix strings drift faster than anything else in a Pusher integration. Log every trigger() with channel, event, and payload size in non-production, but note that encrypted payloads are opaque in the Pusher debug console, so your own logs become the primary debugging surface.

Gotchas and Tips

  • Still a dead end in Laravel. 6.1.0 proves the package is maintained, which softens an "abandoned" read, but it does not change the verdict: it is a Symfony bundle, and Laravel's native pusher broadcast driver plus PrivateEncryptedChannel already covers everything this release adds. Use it only if you are literally on Symfony, and even then prefer the official SDK plus a thin service. Check composer.json on the 6.1.0 tag for the Symfony/PHP constraints — the 6.x line targets modern Symfony, so Symfony2-era guidance applies only to old tags.
  • Encryption is a channel-name contract, not a config flag. Renaming private-orders to private-encrypted-orders is the whole server-side change; if you expect a config toggle you will spend an hour looking for one. Conversely, subscribing the JS client to a plaintext channel and then expecting decryption fails silently with unreadable payloads.
  • Encryption requires TLS and client support. wss:// only, and the pusher-js build on the page must be new enough to decrypt. A pinned old JS bundle is the most likely cause of "channel subscribed, events arrive, data is garbage."
  • Master key rotation invalidates shared secrets. If you rotate the encryption master key pair in the Pusher dashboard, existing clients hold channel secrets derived from the old key. Expect to force re-authorization (reconnect the client) after rotation; plan it as a deploy, not a dashboard click.
  • Cluster is mandatory. Omitting options.cluster produces connection errors that look like bad credentials. Set it explicitly in config and in the JS client.
  • Secrets leak easily. The most common mistake is dumping the whole lopi_pusher config (secret included) into a Twig/Blade variable. Only render key and cluster. The encryption master key never touches your front end or your config dump.
  • Pusher limits will bite silently. 10 channels per trigger() call, ~10KB payload — and note that encryption inflates payload size, so anything close to the limit before may now exceed it. Batch logic that "works" in dev can drop events under load; chunk channels and validate payload size before triggering.
  • Error handling. Pusher\Pusher::trigger() throws PusherException on transport/auth failures. Wrap calls in try/catch, log the exception, and decide whether the event is critical (fail the request) or fire-and-forget (queue it).
  • Testing. There's no built-in fake like Laravel's Event::fake() for broadcasting. Mock the lopi_pusher service (or your PusherService wrapper) in unit tests, and assert on the arguments passed to trigger() rather than hitting the Pusher API. Test that your encrypted channel names carry the private-encrypted- prefix and that your auth endpoint returns the SDK-generated payload — those two assertions catch the majority of encryption regressions.
  • Extension points. The bundle's service definition and Twig extension are the customization seams — override the service in your app config or decorate the Twig extension rather than editing vendor code. When porting to Laravel, that seam becomes a ServiceProvider binding and a Blade directive.
  • Version drift. 6.1.0 adds an SDK expectation around encryption; pin pusher/pusher-php-server to a version the bundle's constraint allows and that supports encrypted channels, and run composer why pusher/pusher-php-server before upgrading either side independently.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource