Giao diện
Broadcasting
Giới thiệu (Introduction)
Trong nhiều ứng dụng web hiện đại, WebSockets được sử dụng để xây dựng giao diện cập nhật theo thời gian thực (realtime). Khi dữ liệu thay đổi trên server, message được gửi qua WebSocket connection để client xử lý — hiệu quả hơn nhiều so với polling liên tục.
Laravel giúp "broadcast" (phát sóng) server-side events qua WebSocket connection dễ dàng, cho phép chia sẻ cùng event names và data giữa server-side và client-side JavaScript.
Drivers hỗ trợ
Laravel bao gồm 3 server-side broadcasting drivers:
| Driver | Mô tả |
|---|---|
| Laravel Reverb | WebSocket server tích hợp sẵn cho Laravel |
| Pusher Channels | Dịch vụ WebSocket hosted |
| Ably | Nền tảng realtime messaging |
Cài đặt nhanh (Quickstart)
Server Side
Cài đặt và cấu hình broadcasting channel:
bash
php artisan install:broadcastingClient Side
Cài đặt Laravel Echo — JavaScript library lắng nghe events:
bash
npm install --save-dev laravel-echo pusher-jsTổng quan khái niệm (Concept Overview)
Broadcasting Laravel cho phép broadcast server-side events đến client-side JavaScript application qua cách tiếp cận driver-based. Events phát sóng qua channels:
- Public channels: Bất kỳ visitor nào đều có thể subscribe
- Private channels: User phải authenticated và authorized
- Presence channels: Kênh private, thêm khả năng biết ai đang online
Luồng hoạt động
- User thực hiện action (ví dụ: tạo đơn hàng)
- Server fire event implement
ShouldBroadcast - Event được broadcast qua WebSocket driver
- Client-side JavaScript (Echo) nhận và xử lý event
Cấu hình Reverb
Reverb là WebSocket server của chính Laravel:
bash
php artisan install:broadcastingCấu hình trong .env:
env
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secretKhởi động Reverb server:
bash
php artisan reverb:startClient-Side với Reverb
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'],
});Định nghĩa Broadcast Events
Implement interface ShouldBroadcast trong event class:
php
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
class ServerCreated implements ShouldBroadcast
{
use SerializesModels;
public function __construct(
public User $user,
) {}
/**
* Channels mà event broadcast.
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('user.'.$this->user->id),
];
}
}Broadcast Name
Mặc định dùng tên class. Tùy chỉnh:
php
public function broadcastAs(): string
{
return 'server.created';
}Broadcast Data
php
public function broadcastWith(): array
{
return ['id' => $this->user->id];
}Broadcast Queue
php
public $connection = 'sqs';
public $queue = 'broadcasting';Authorizing Channels (Xác thực Channels)
Private và Presence channels yêu cầu authorization. Định nghĩa trong routes/channels.php:
php
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});Broadcasting Events
Fire event như bình thường:
php
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);Only to Others
Khi user trigger action, broadcast đến mọi người trừ user hiện tại:
php
broadcast(new ShippingStatusUpdated($update))->toOthers();Anonymous Events
Broadcast events không cần tạo event class:
php
use Illuminate\Broadcasting\Channel;
Broadcast::on(new Channel('orders'))->send(['status' => 'shipped']);Nhận Broadcasts (Receiving Broadcasts)
Lắng nghe Events
js
Echo.channel('orders')
.listen('OrderShipmentStatusUpdated', (e) => {
console.log(e.order.name);
});Private Channels
js
Echo.private(`orders.${this.order.id}`)
.listen('OrderShipmentStatusUpdated', (e) => {
console.log(e.order.name);
});Presence Channels
Biết ai đang online:
js
Echo.join(`chat.${roomId}`)
.here((users) => {
// Danh sách users online...
})
.joining((user) => {
// User mới tham gia...
})
.leaving((user) => {
// User rời đi...
});Client Events
Gửi events từ client (không phải server):
js
Echo.private(`chat.${roomId}`)
.whisper('typing', {
name: this.user.name
});Lắng nghe client events:
js
Echo.private(`chat.${roomId}`)
.listenForWhisper('typing', (e) => {
console.log(e.name);
});Notifications
Kết hợp với Notifications — broadcast notifications đến JavaScript:
js
Echo.private(`App.Models.User.${userId}`)
.notification((notification) => {
console.log(notification.type);
});