Laravel Redis 廣播 例項

iwhao發表於2018-10-22

先附上 github地址

github.com/wanghao-fan/laravel-ech...

本 文中 僅使用了 redis的廣播驅動

思路

laravel 的廣播系統和佇列系統類似,需要兩個程式協作,一個是 laravel 的 web 後臺系統,另一個是 Socket.IO 伺服器系統。具體的流程是頁面載入時,網頁 js 程式 Laravel Echo 與 Socket.IO 伺服器建立連線, laravel 發起透過驅動釋出廣播,Socket.IO 伺服器接受廣播內容,對連線的客戶端網頁推送資訊,以達到網頁實時更新的目的。

配置

配置檔案 config/broadcasting.php,可以直接在 .env 中配置以下程式碼

BROADCAST_DRIVER=redis

廣播服務提供者

config/app.php 配置檔案中 providers陣列中開啟註釋

App\Providers\BroadcastServiceProvider::class,

CSRF令牌

Laravel Echo需要訪問當前 Session 的 CSRF 令牌(token)

自建立的 blade檢視的 head中 加入 meta標籤

<meta name="csrf-token" content="{{ csrf_token() }}">

Redis

Redis廣播需要安裝 Predis庫

composer require predis/predis

安裝Laravel Echo

Laravel Echo是一個JavaScript庫,web端可以輕鬆訂閱頻道並收聽Laravel廣播的事件
透過 npm 包管理器安裝 Echo

npm install
npm install -g laravel-echo-server

初始化 laravel-echo-server

laravel-echo-server init

// 是否在開發模式下執行此伺服器(y/n) 輸入y
? Do you want to run this server in development mode? (y/N) 

// 設定伺服器的埠 預設 6001 輸入 6001就可以了 或者你想要的
? Which port would you like to serve from? (6001)

// 想用的資料庫  選擇 redis
? Which database would you like to use to store presence channel members? (Use arrow keys)
❯ redis 
  sqlite 

//   這裡輸入 你的laravel  專案的訪問域名
? Enter the host of your Laravel authentication server. (http://localhost) 

// 選擇 網路協議 http
? Will you be serving on http or https? (Use arrow keys)
❯ http 
  https 

// 您想為HTTP API生成客戶端ID/金鑰嗎 N
? Do you want to generate a client ID/Key for HTTP API? (y/N) 

// 要設定對API的跨域訪問嗎?(y/n)N
Configuration file saved. Run laravel-echo-server start to run server.

設定完成後 專案根目錄 下 會生成 laravel-echo-server.json 檔案 這裡面就是剛才的配置

執行命令啟動 服務 出現如下 則啟動成功

laravel-echo-server start

L A R A V E L  E C H O  S E R V E R

version 1.4.2

⚠ Starting server in DEV mode...

✔  Running at localhost on port 6001
✔  Channels are ready.
✔  Listening for http events...
✔  Listening for redis events...

Server ready!

頻道

頻道必須是 Channel、PrivateChannel 或 PresenceChannel 的例項。Channel 例項表示任何使用者都可以訂閱的公開頻道,而 PrivateChannels 和 PresenceChannels 則表示需要 頻道授權 的私有頻道:

建立事件

php artisan make:event PublicMessageEvent 

檔案生成目錄 app/Events

// 訊息內容
public $message;

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

// 返回一個公共頻道 頻道名稱為push
public function broadcastOn()
{
    return new Channel('push');
}

// Laravel 預設會使用事件的類名作為廣播名稱來廣播事件,自定義:
public function broadcastAs()
{
    return 'push.message';
}

新增路由

 use App\Events\PublicMessageEvent;
 Route::get('/echo', function () {
    return view('echo');
 });

Route::get('/push/{message}', function ($message) {
    broadcast(new PublicMessageEvent($message));
})

前端

安裝 laravel-echo

npm install laravel-echo

編輯 resource/js/bootstrap.js 新增如下程式碼

import Echo from "laravel-echo"

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001'
});

編輯 resource/js/app.js 新增如下程式碼

Echo.channel('push')
.listen('.push.message', (e) => {
    alert('來了')
    console.log(e);
});

建立 echo.blade.php

head 中加上

 <meta name="csrf-token" content="{{ csrf_token() }}">
 <script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>

 <script src="/js/app.js"></script>

編譯 js 檔案

npm run watch

瀏覽器訪問 專案域名/echo

瀏覽器訪問 專案域名/push/這是一個測試廣播

echo 頁面 會自動彈出

到這 廣播 釋出到公共頻道就完成了

私有頻道 PrivateChannel

建立事件

php artisan make:event PrivateMessageEvent

PrivateMessageEvent 中 寫入 以下內容

class PrivateMessageEvent implements ShouldBroadcast
{

    // 訊息內容
    public $message;
    // 使用者
    public $user;

    public function __construct(User $user, string $message)
    {
        $this->user = $user;
        $this->message = $message;
    }

    // 建立私有頻道
    public function broadcastOn()
    {
        return new PrivateChannel('privatePush.' . $this->user->id);
    }

    //    //Laravel 預設會使用事件的類名作為廣播名稱來廣播事件,自定義:
    //    public function broadcastAs()
    //    {
    //        return 'privatePush.message';
    //    }

    // 控制廣播資料:
    public function broadcastWith()
    {
        return ['message' => $this->message,'status' => 'okok'];
    }
}

新增發布廣播到私有頻道 觸發路由 routes/web

Route::get('/privatePush/{message}/{id}', function ($message, $id) {
    $user = \App\User::find($id);
    if (empty($user)) return '無此使用者';
    broadcast(new PrivateMessageEvent($user, $message));
});

頻道授權

定義授權路由 routes/channel 中加入一下程式碼

Broadcast::channel('privatePush.{id}', function ($user, $id) {
    return (int) $user->id === (int) $id;
});

前端

echo.blade.php 中加入

<script>
    @if(!empty(Auth::user()))
        window.id = "{{Auth::user()->id}}"
    @endif
</script>

app.js

Echo.private('privatePush.' + window.id)
.listen('PrivateMessageEvent', (e) => {
    alert('qweqwe')
    console.log(e);
});

我的部落格

我的掘金

我的簡書

Laravel China

我的微信公眾號

本作品採用《CC 協議》,轉載必須註明作者和本文連結
安靜的美男子

相關文章