10 KiB
10 KiB
name, description, license, metadata
| name | description | license | metadata | ||
|---|---|---|---|---|---|
| echo-development | Develops real-time broadcasting with Laravel Echo. Activates when setting up broadcasting (Reverb, Pusher, Ably); creating ShouldBroadcast events; defining broadcast channels (public, private, presence, encrypted); authorizing channels; configuring Echo; listening for events; implementing client events (whisper); setting up model broadcasting; broadcasting notifications; or when the user mentions broadcasting, Echo, WebSockets, real-time events, Reverb, or presence channels. | MIT |
|
Laravel Broadcasting & Echo
When to Apply
Activate this skill when:
- Installing or configuring Laravel broadcasting (Reverb, Pusher, Ably)
- Creating events that implement
ShouldBroadcast - Defining broadcast channels and authorization
- Setting up Laravel Echo on the client side
- Listening for broadcast events, notifications, or model events
- Implementing client-to-client events (whisper)
- Working with presence channels for user awareness
Documentation
Use search-docs for detailed broadcasting patterns and documentation.
Basic Usage
Installing Broadcasting
php artisan install:broadcasting
Use flags for specific drivers: --reverb, --pusher, --ably. This creates config/broadcasting.php and routes/channels.php.
Creating a Broadcast Event
php artisan make:event OrderShipped
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
class OrderShipped implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public function __construct(public Order $order) {}
public function broadcastOn(): array
{
return [new PrivateChannel('orders.'.$this->order->id)];
}
}
Dispatch the event:
use App\Events\OrderShipped;
OrderShipped::dispatch($order);
Authorizing Channels
Define authorization in routes/channels.php:
use App\Models\Order;
use App\Models\User;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
Create a channel class for complex authorization:
php artisan make:channel OrderChannel
List all registered channels:
php artisan channel:list
Client-Side Setup
Install Echo and Pusher JS:
npm install --save-dev laravel-echo pusher-js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
Listening for Events
Echo.private(`orders.${orderId}`)
.listen('OrderShipmentStatusUpdated', (e) => {
console.log(e.order);
});
Running Required Processes
php artisan queue:work # Required for ShouldBroadcast events
php artisan reverb:start # Required for Reverb driver
What's Possible
Use search-docs to find detailed code examples and configuration for each of these:
Channel Types
- Public (
new Channel) — no auth, anyone can subscribe. Use for app-wide announcements, public feeds, or status pages. - Private (
new PrivateChannel) — requires authorization. Use for user-specific data like orders, messages, or account updates. - Presence (
new PresenceChannel) — authorized + tracks who's online. Use for chat rooms, collaborative editing, "who's viewing this" features, or typing indicators. - EncryptedPrivate — end-to-end encryption, Pusher/Reverb only. Use when payload must be hidden from the broadcast server (e.g., sensitive financial data or private messages).
- Drivers:
reverb(self-hosted WebSocket server),pusher(managed service),ably(managed service),log(writes to Laravel log, use for debugging),null(no-op, use for testing)
Event Customization
broadcastAs()— custom event name (client must use dot prefix:.listen('.custom.name')). Use when you want stable API names decoupled from PHP class names, or shorter event names for the frontend.broadcastWith()— control exact payload. Use to avoid leaking sensitive model attributes, slim down large payloads, or add computed data not on the model.broadcastWhen()— conditional broadcasting. Use to skip broadcasting when changes are trivial (e.g., only broadcast order updates above a threshold, or skip unchanged fields).broadcastQueue()/$queue— route to specific queue. Use to isolate real-time broadcasts from slow background jobs so they're processed faster.$connection— set queue connection per event. Use when broadcasts should go through a faster queue backend like Redis while other jobs use the database driver.
Broadcasting Interfaces
ShouldBroadcast— queue the broadcast (default). Use for most events to avoid blocking the HTTP response.ShouldBroadcastNow— broadcast synchronously, skip queue. Use during development or for time-critical events where queue latency is unacceptable.ShouldDispatchAfterCommit— wait for DB transaction commit. Use when the event references newly created records that listeners need to query (prevents race conditions).ShouldRescue— auto-catch broadcast exceptions. Use to prevent broadcast failures (e.g., WebSocket server down) from disrupting the user's HTTP request.InteractsWithSockets— required fortoOthers(). Use on any event where you want to exclude the sender (optimistic UI updates).InteractsWithBroadcasting— override driver per event viabroadcastVia(). Use in multi-driver setups (e.g., some events via Reverb, others via Pusher).
Broadcasting Helpers
broadcast(new Event)->toOthers()— exclude current user's socket. Use when the client already updates optimistically from the API response to avoid duplicate updates.broadcast(new Event)->via('pusher')— override connection. Use to route specific events through a different broadcast driver than the default.Broadcast::on(),Broadcast::private(),Broadcast::presence()— anonymous broadcasting without event classes. Chain.as('name')->with($data)->send()or.sendNow(). Use for simple one-off broadcasts where creating a full event class is overkill (e.g., quick status updates, simple notifications).
Channel Authorization
- Closure-based in
routes/channels.php— use for simple authorization logic (e.g., checking ownership). - Model binding:
Broadcast::channel('orders.{order}', fn (User $user, Order $order) => ...)— use when authorization depends on the model instance (auto-resolves from route parameter). - Channel classes via
php artisan make:channel— use for complex authorization logic that benefits from dependency injection or reusable logic across channels. - Multiple guards:
['guards' => ['web', 'admin']]— use when the channel should be accessible by users authenticated via different guards (e.g., both regular users and admins).
Model Broadcasting
BroadcastsEventstrait auto-broadcasts created/updated/deleted/trashed/restored. Use to automatically keep clients in sync with Eloquent model changes without writing individual events.- Channel convention:
App.Models.Post.{id}— clients subscribe to model-specific channels. broadcastAs($event)andbroadcastWith($event)for per-action customization. Use to send different payloads for create vs update, or suppress certain event types.newBroadcastableEvent($event)for event instance customization (e.g.,->dontBroadcastToCurrentUser()). Use when you need to modify the underlying event object before it's dispatched.
Client-Side Features
- Client events:
whisper()/listenForWhisper()— peer-to-peer without server roundtrip (private/presence channels only). Use for typing indicators, cursor positions, or any ephemeral state that doesn't need server persistence. - Presence channels:
Echo.join()withhere(),joining(),leaving(),error()callbacks. Use for showing online users, "X is viewing this document" features, or live participant counts. - Notification broadcasting:
.notification()on user's private channel. Use to show real-time notifications (toast, badge counts) pushed from Laravel's notification system. - Connection management:
Echo.connectionStatus(),Echo.leaveAllChannels(),Echo.disconnect(). Use to show connection indicators, clean up on logout, or handle offline/reconnect scenarios. - Custom namespace:
new Echo({ namespace: 'App.Other.Namespace' }). Use when your events live outside the defaultApp\Eventsnamespace.
Common Pitfalls
- Queue worker must be running for
ShouldBroadcastevents. UseShouldBroadcastNowduring development. BROADCAST_CONNECTIONnotBROADCAST_DRIVER: Laravel 11+ renamed this env key.toOthers()requiresInteractsWithSocketstrait ANDX-Socket-IDheader. Echo auto-adds this to global Axios. Forfetch, manually sendEcho.socketId().- CORS: When frontend/backend are on different origins, add
broadcasting/authtoconfig/cors.phppaths and setsupports_credentialstotrue. - Missing
VITE_prefix: Client-side env vars must start withVITE_. channels.phpnot loaded: Verify it's included inwithRouting()inbootstrap/app.php.- Reverb is long-running: Code changes require
php artisan reverb:restart. - Presence channel auth must return an array of user data (
['id' => $user->id, 'name' => $user->name]), nottrue. Returningtruesilently fails. - Dot prefix rule: When using
broadcastAs(), client must prefix with.(e.g.,.listen('.custom.name')). Without the dot, Echo looks forApp\Events\custom.namewhich silently fails. - Reverb host separation:
REVERB_SERVER_HOST/REVERB_SERVER_PORT(internal bind) vsREVERB_HOST/REVERB_PORT(public address) vsVITE_REVERB_HOST/VITE_REVERB_PORT(client JS). - Sanctum SPA auth: Ensure
/broadcasting/authusesauth:sanctummiddleware and CSRF tokens are sent withwithCredentials: true.