Laravel Echo, Broadcasting, WebSockets
# Cài đặt dependencies
composer require pusher/pusher-php-server
# Frontend
npm install --save-dev laravel-echo pusher-js
<?php
// .env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-secret
PUSHER_APP_CLUSTER=ap1
// config/broadcasting.php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
],
// resources/js/bootstrap.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
forceTLS: true
});
// Lắng nghe public channel
Echo.channel('orders')
.listen('OrderShipped', (e) => {
console.log('Order shipped:', e.order);
});
// Private channel (requires auth)
Echo.private(`orders.${userId}`)
.listen('OrderStatusChanged', (e) => {
console.log('Your order:', e.order.status);
});
// Presence channel (who's online)
Echo.join(`chat.${roomId}`)
.here((users) => {
console.log('Users in room:', users);
})
.joining((user) => {
console.log('User joined:', user.name);
})
.leaving((user) => {
console.log('User left:', user.name);
})
.listen('MessageSent', (e) => {
console.log('New message:', e.message);
});
<?php
// app/Events/MessageSent.php
namespace App\Events;
use App\Models\Message;
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;
use Illuminate\Queue\SerializesModels;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(
public Message $message
) {}
// Public channel - ai cũng nghe được
public function broadcastOn(): Channel
{
return new Channel('chat');
}
// Private channel - cần auth
public function broadcastOn(): PrivateChannel
{
return new PrivateChannel('chat.' . $this->message->room_id);
}
// Presence channel - biết ai online
public function broadcastOn(): PresenceChannel
{
return new PresenceChannel('chat.' . $this->message->room_id);
}
// Customize broadcast data
public function broadcastWith(): array
{
return [
'id' => $this->message->id,
'content' => $this->message->content,
'user' => [
'id' => $this->message->user->id,
'name' => $this->message->user->name,
],
'created_at' => $this->message->created_at->toIso8601String(),
];
}
// Custom event name
public function broadcastAs(): string
{
return 'message.sent';
}
}
// routes/channels.php - Authorization
Broadcast::channel('chat.{roomId}', function ($user, $roomId) {
return $user->rooms()->where('id', $roomId)->exists();
});
// Dispatch
broadcast(new MessageSent($message));
broadcastWith() để kiểm soát data
gửi đi, tránh expose sensitive data.