php erb 116 lines · 4 tabs

Broadcasting a Chat Message with Laravel Echo and Blade Components

Shared by codesnips Aug 2026
4 tabs
<?php

use App\Models\Conversation;
use App\Models\User;
use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('chat.{conversationId}', function (User $user, int $conversationId) {
    $conversation = Conversation::find($conversationId);

    if (! $conversation) {
        return false;
    }

    return $conversation->participates($user);
});
4 files · php, erb Explain with highlit

This snippet shows the full round-trip of a real-time chat message in Laravel: persisting it, broadcasting it over a private channel, and rendering it client-side into a Blade-defined DOM node. The core idea is that broadcasting decouples the HTTP request that creates a message from the delivery of that message to every other connected participant. The sender's request returns immediately after the write, while a queued event fans the payload out to WebSocket subscribers.

In MessageSent event, the class implements ShouldBroadcast, which is what tells Laravel to push this event onto a broadcast driver (Pusher, Reverb, or Ably) rather than only dispatching it in-process. broadcastOn() returns a PrivateChannel scoped to the conversation id, so only authorized members receive it. broadcastAs() renames the wire event to a stable message.sent string instead of the fully-qualified class name, which keeps the JavaScript listener decoupled from PHP namespaces. broadcastWith() shapes a lean payload — deliberately not the whole model — to avoid leaking columns and to keep frames small. Implementing ShouldQueue alongside ShouldBroadcast means the actual push happens on a worker, so a slow WebSocket provider never blocks the web request.

SendMessageController handles the create path. It validates input, associates the message with the authenticated user via the relationship, and then calls broadcast(new MessageSent($message))->toOthers(). The toOthers() modifier is important: it excludes the current socket connection from delivery so the sender does not receive a duplicate of a message it already rendered optimistically. The controller returns the saved model as JSON for the sender's own UI.

channels.php defines the authorization callback for chat.{conversationId}. Private and presence channels require this gate; returning a truthy value authorizes the subscription, and here membership is checked through participates(). Without this, PrivateChannel subscriptions are rejected.

Finally, message-list.blade.php pairs a server-rendered <x-chat.message> component template with an Alpine listener bound through Echo. The echo-private directive subscribes to the channel, and incoming message.sent events are appended to a reactive array, reusing the same markup contract as the initial server render. The trade-off is added infrastructure (a broadcast server plus queue workers) in exchange for push updates without polling.


Related snips

Share this code

Here's the card — post it anywhere.

Broadcasting a Chat Message with Laravel Echo and Blade Components — share card
Link copied