Laravel Echo 聊天系統 WebSocket

什麼是 WebSocket

WebSocket 允許在客戶端和伺服器之間建立持久性的、全雙工連接,以便即時資料能夠雙向傳輸:

  1. 全雙工通信:伺服器與客戶端都可以主動傳送資料,無需等待請求。
  2. 低延遲:連接建立後持續使用,不像 HTTP 每次都要重新連線。
  3. 持久性連接:連線長時間保持開啟,避免反覆建立連線的成本。
  4. 即時性:適用於即時聊天、線上遊戲、即時地圖等需要即時資料的應用。
  5. 跨域通信:不受同源政策限制,可進行跨域資料傳輸。
  6. 簡單的 API:現代瀏覽器提供簡單易用的 WebSocket API。

在 Laravel 中使用 Broadcasting

Broadcast 建立在 Laravel 的事件系統之上,用來推送即時事件與訊息:

  1. 即時通知:透過 WebSocket 傳送資料至客戶端,立即更新。
  2. 多用戶即時互動:如聊天室、協作應用、多人遊戲。
  3. 監聽事件:客戶端可訂閱事件頻道,接收伺服器端廣播的資料。

Server Side:Laravel Echo

Laravel Echo 官方文件

Laravel Echo 是 Laravel 為整合 WebSocket 推出的前端套件,支援 Pusher、Socket.IO、Ably 等驅動。


Client Side:Pusher

Pusher 官方網站

Pusher 是一個即時通信平台,基於 WebSocket 技術提供即時訊息服務,簡化實作:

  • 即時消息傳遞:用於聊天、通知、推播等功能。
  • 即時更新 UI:如即時更新列表、通知提示。
  • 多平台支援:Web、iOS、Android、桌面應用。
  • 事件驅動架構:支援自定義事件觸發與監聽。
  • 安全性:支援用戶認證與頻道授權。

使用步驟:

  1. 註冊 Pusher 帳號並建立 App,取得 App Key、App ID、Secret、Cluster 等。
  2. 安裝套件:
composer require pusher/pusher-php-server
npm install --save laravel-echo pusher-js
  1. 配置 config/broadcasting.php
'connections' => [
    '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, // Laravel 8+ 改為 useTLS
        ],
    ],
],
  1. 配置 .env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_APP_CLUSTER=your-cluster
  1. 前端設定 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
});

Laravel 8+ 建議使用 Vite 搭配 import.meta.env 取代 process.env.MIX_*


Broadcasting 頻道類型

Private Channel

  • 使用場景:一對一私訊、用戶通知等。
  • 權限控管:只能由授權用戶接收。
  • 命名慣例:private-channel-name

Presence Channel

  • 類似 Private Channel,但可以追蹤用戶狀態(加入、離開)。
  • 使用場景:聊天室成員列表、即時協作工具。
  • 命名慣例:presence-channel-name
  • 可透過事件如 .here().joining().leaving() 得知頻道內成員。

建立與廣播事件

  1. 建立事件:
php artisan make:event MessageSent
  1. 實作 ShouldBroadcast 介面於事件類別:
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class MessageSent implements ShouldBroadcast
{
    use InteractsWithSockets;

    public $message;

    public function __construct($message)
    {
        $this->message = $message;
    }

    public function broadcastOn()
    {
        return new PrivateChannel('chat.' . $this->message->to_user_id);
    }

    public function broadcastWith()
    {
        return [
            'message' => $this->message->content,
        ];
    }
}
  1. 觸發事件:
event(new MessageSent($message));

前端監聽事件

window.Echo.private('chat.' + userId)
    .listen('MessageSent', (e) => {
        console.log('收到訊息:', e.message);
    });

其他 Broadcaster 支援

除了 Pusher 外,Laravel 也支援:

  • Ably:免費層提供 WebSocket 傳輸,支援 Laravel Echo。

  • Redis + Socket.IO (Laravel Websockets)

    • 使用 beyondcode/laravel-websockets 套件自架 WebSocket Server。
    • 可搭配 Laravel Echo 使用,免額外服務費。
    • 安裝教學:Laravel WebSockets GitHub