Laravel Broadcasting — Real-Time Events with WebSockets
In this tutorial, you will learn about Laravel Broadcasting. We cover key concepts, practical examples, and best practices to help you master this topic.
Laravel broadcasting enables real-time Websocket communication using Pusher, Reverb, or other drivers, with Laravel Echo on the frontend subscribing to events over channels.
What You'll Learn
By the end of this tutorial, you'll set up broadcasting with Reverb, define broadcast events, create public/private/presence channels, use Laravel Echo, and implement real-time features.
Why Broadcasting Matters
Real-time features like live chat, notifications, and collaborative editing require server-push capabilities that HTTP polling cannot efficiently provide.
Real-World Use
A collaboration platform broadcasts task updates to all team members. When a user completes a task, the event triggers a notification and updates the task board for all connected clients.
Broadcasting Path
flowchart LR
A[Laravel Framework] --> B[Broadcasting]
B --> C[Reverb]
B --> D[Pusher]
B --> E[Echo]
B --> F[Channels]
B --> G{You Are Here}
style G fill:#f90,color:#fff
Broadcasting Configuration
Configure Reverb (Laravel's first-party WebSocket server).
composer require laravel/reverb
php artisan reverb:install
<?php
// config/broadcasting.php
"connections" => [
"reverb" => [
"driver" => "reverb",
"key" => env("REVERB_APP_KEY"),
"secret" => env("REVERB_APP_SECRET"),
"app_id" => env("REVERB_APP_ID"),
"options" => [
"host" => env("REVERB_HOST", "localhost"),
"port" => env("REVERB_PORT", 8080),
"scheme" => env("REVERB_SCHEME", "http"),
],
"client_options" => [],
],
],
Broadcast Events
Create and configure broadcastable events.
<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
class OrderShipped implements ShouldBroadcast {
use Dispatchable, InteractsWithSockets;
public function __construct(
public Order $order,
) {}
public function broadcastOn(): array {
return [
new PrivateChannel("orders.{$this->order->id}"),
new Channel("admin.orders"),
];
}
public function broadcastWith(): array {
return [
"id" => $this->order->id,
"status" => $this->order->status,
"total" => $this->order->total,
];
}
public function broadcastAs(): string {
return "order.shipped";
}
}
Laravel Echo Client
Listen for events on the frontend.
import Echo from "laravel-echo";
import Pusher from "pusher-js";
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,
forceTLS: false,
enabledTransports: ["ws", "wss"],
});
// Listen on private channel
Echo.private("orders.1")
.listen(".order.shipped", (e) => {
alert(`Order #${e.id} shipped!`);
});
// Listen on public channel
Echo.channel("admin.orders")
.listen(".order.shipped", (e) => {
toastr.success(`Order ${e.id} shipped`);
});
Presence Channels
Track connected users in real-time.
<?php
namespace App\Events;
use Illuminate\Broadcasting\PresenceChannel;
class UserTyping implements ShouldBroadcast {
public function __construct(public string $roomId, public string $userName) {}
public function broadcastOn(): array {
return [new PresenceChannel("chat.{$this->roomId}")];
}
}
// Frontend
Echo.join("chat.room1")
.here((users) => {
console.log("Connected users:", users);
})
.joining((user) => {
console.log("User joined:", user.name);
})
.leaving((user) => {
console.log("User left:", user.name);
})
.listen(".typing", (e) => {
showTypingIndicator(e.userName);
});
Channel Authorization
Authorize private and presence channels.
<?php
// routes/channels.php
use App\Models\Order;
use App\Models\User;
Broadcast::channel("orders.{orderId}", function (User $user, int $orderId) {
$order = Order::findOrFail($orderId);
return $user->id === $order->user_id || $user->isAdmin();
});
Broadcast::channel("chat.{roomId}", function (User $user, string $roomId) {
return ["id" => $user->id, "name" => $user->name, "avatar" => $user->avatar_url];
});
Common Mistakes
1. Broadcasting Sensitive Data
Broadcast events send data to all subscribers. Never include passwords, tokens, or PII.
2. Not Using Private Channels for User-Specific Data
Using public channels for private data exposes it to unauthorized users.
3. Forgetting broadcastAs for Custom Event Names
Without broadcastAs, the event class name is used. Custom names are cleaner for frontend.
4. Broadcasting Too Many Events
High-frequency events overwhelm the WebSocket server. Throttle with debouncing.
5. Not Securing WebSocket Connections
WebSocket endpoints should use WSS in production and require authentication where needed.
Practice Questions
1. What is the difference between Channel and PrivateChannel?
Channel is public access. PrivateChannel requires authorization.
2. What is a presence channel?
A private channel that tracks which users are currently connected.
3. How do you customize the broadcast event name?
Use broadcastAs() method and prefix with a dot in Echo.
4. What does broadcastWith() control?
The data sent to clients when the event is broadcast.
5. Challenge: Create a real-time notification system.
<?php
class NotificationSent implements ShouldBroadcast {
public function broadcastOn(): array {
return [new PrivateChannel("notifications.{$this->userId}")];
}
public function broadcastAs(): string {
return "notification.sent";
}
}
// Listen
Echo.private("notifications.1")
.listen(".notification.sent", (e) => showNotification(e));
FAQ
Mini Project: Real-Time Chat Application
Implement a real-time chat with presence channels.
<?php
class MessageSent implements ShouldBroadcast {
public function broadcastOn(): array {
return [new PresenceChannel("chatroom.{$this->chatroomId}")];
}
public function broadcastAs(): string {
return "message.sent";
}
}
What's Next
Laravel Notifications Laravel Queues Deep Laravel Cache Deep
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro