laravel/reverb
Laravel Reverb adds real-time WebSocket support to Laravel, enabling broadcasting and live updates with a first-party, self-hosted server and seamless Laravel integration. Ideal for chat, notifications, and presence features.
Installation:
composer require laravel/reverb
php artisan reverb:install
This publishes the config, creates a Redis pub/sub connection, and sets up the WebSocket server.
Configuration:
Update .env with your Redis connection details:
BROADCAST_DRIVER=redis
REVERB_REDIS_URL=redis://127.0.0.1:6379
REVERB_PORT=6001
REVERB_HOST=127.0.0.1
First Use Case: Broadcast an event to a channel:
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('chat', function ($user) {
return ['id' => $user->id];
});
// In a controller or event
Broadcast::to('chat')->send('New message!');
Client-Side Connection: Connect using JavaScript with the Reverb server:
const socket = new WebSocket(`ws://${window.location.hostname}:6001`);
socket.onmessage = (event) => console.log(event.data);
Channel Management:
Broadcast::channel('user.{user}', function ($user) {
return ['id' => $user->id];
});
Broadcast::presenceChannel():
Broadcast::presenceChannel('chat', function ($user, $room) {
return ['user_id' => $user->id, 'room_id' => $room->id];
});
Event Broadcasting:
class NewMessage implements ShouldBroadcast
{
public $message;
public function __construct($message)
{
$this->message = $message;
}
public function broadcastOn()
{
return new Channel('chat');
}
}
broadcastAs() for private channels:
public function broadcastAs()
{
return 'private-message';
}
Authentication:
Broadcast::auth() in channels:
Broadcast::channel('private-chat.{user}', function ($user) {
return ['id' => $user->id];
}, function ($user, $options) {
return $user->api_token === $options['token'];
});
const socket = new WebSocket(`ws://${window.location.hostname}:6001?token=${userToken}`);
Scaling and Load Balancing:
config/reverb.php:
'connection_limits' => [
'max_connections' => 1000,
'max_connections_per_ip' => 100,
],
Rate Limiting:
config/reverb.php:
'rate_limiting' => [
'enabled' => true,
'max_attempts' => 100,
'decay_seconds' => 60,
],
Pusher Compatibility:
// In routes/web.php
Route::post('/pusher/auth', [PusherAuthController::class, 'auth']);
APP_KEY and APP_ENV are set correctly for Pusher compatibility.Laravel Echo: Configure Echo to use Reverb:
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'reverb',
key: process.env.MIX_PUSHER_APP_KEY,
wsHost: window.location.hostname,
wsPort: 6001,
forceTLS: false,
disableStats: true,
});
Testing:
ReverbTestCase for WebSocket tests:
use Laravel\Reverb\Testing\ReverbTestCase;
class ChatTest extends ReverbTestCase
{
public function test_broadcasting()
{
$this->broadcastingTo('chat')
->then(function ($event) {
$this->assertEquals('Hello!', $event['message']);
});
Broadcast::to('chat')->send('Hello!');
}
}
Custom Middleware: Extend Reverb’s middleware for custom logic:
namespace App\Broadcasting;
use Laravel\Reverb\Middleware\Authenticate;
class CustomAuthenticate extends Authenticate
{
public function handle($request, Closure $next)
{
// Custom auth logic
return $next($request);
}
}
Register in config/reverb.php:
'middleware' => [
\App\Broadcasting\CustomAuthenticate::class,
],
Monitoring:
redis-cli monitor
app/Providers/ReverbServiceProvider.php:
Reverb::connection()->on('connecting', function ($connection) {
Log::info('New connection', ['socket_id' => $connection->id]);
});
Redis Connection Issues:
REVERB_REDIS_URL in .env:
REVERB_REDIS_URL=redis://user:pass@127.0.0.1:6379/0
redis-cli ping to verify Redis connectivity.CORS Errors:
config/reverb.php:
'allowed_origins' => [
'http://localhost:3000',
'https://your-app.com',
],
* for development (not production):
'allowed_origins' => ['*'],
Memory Leaks:
activity_timeout is set in config/reverb.php:
'activity_timeout' => 60, // seconds
php artisan reverb:stats to check active connections.Event Data Serialization:
broadcastWith():
public function broadcastWith()
{
return ['message' => $this->message, 'user' => $this->user->toArray()];
}
Pusher HTTP API Mismatches:
APP_KEY and APP_ENV match between Reverb and your app:
// In PusherAuthController
public function auth()
{
return Broadcast::auth(config('broadcasting.connections.reverb'));
}
Channel Data Validation:
// Correct format for presence channels
Broadcast::presenceChannel('chat', function ($user, $room) {
return [
'user_id' => $user->id,
'room_id' => $room->id,
'data' => ['custom' => 'value'], // Optional
];
});
Logging:
Enable debug logging in config/reverb.php:
'log_level' => 'debug',
View logs with:
tail -f storage/logs/laravel.log
WebSocket Debugging:
tcpdump or Wireshark to capture WebSocket frames:
tcpdump -i any port 6001 -w reverb.pcap
How can I help you explore Laravel packages today?