websocket 后台新訂單通知 —— Laravel 5.8 workman PHPSocket.IO教程
環境要求:
- Laravel 框架 (5.8 版本)
- Redis 服務
1.安裝 laravel-echo-server
首先我們需要全局安裝 laravel-echo-server ,終端輸入下面的命令
npm install -g laravel-echo-server
安裝完成后,打開你的 Laravel 應用,或新啟一個測試項目
composer create-project --prefer-dist laravel/laravel echo-test
安裝 Predis :
composer require predis/predis
初始化 Socket 服務:
如果你是linux,命令會找不到,推薦你看下這篇帖子
linux下npm安裝的全局命令無法執行
laravel-echo-server init
執行這條命令后,會詢問你一些關於 Socket 服務的配置信息
// 是否在開發模式下運行此服務器(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 start 啟動
laravel-echo-server stop 停止
如果出現報錯,先去啟動你的redis 確認啟動無誤后開始配置 .env
BROADCAST_DRIVER=redis QUEUE_CONNECTION=redis REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379
2.安裝 Socket.io 客戶端和 Laravel-Echo
在這之前建議運行一下 npm install
npm install --save socket.io-client
npm install --save laravel-echo
現在我們先准備客戶端的事情 resources/js/app.js 修改app.js,如果不是5.8自行找對應目錄文件
import Echo from 'laravel-echo' window.io = require('socket.io-client'); window.Echo = new Echo({ broadcaster: 'socket.io', host: window.location.hostname + ':6001' });
終端運行
npm run dev
引入到頁面,我就是先拿首頁來測試了resources/views/welcome.blade.php
// 頭部加入 <meta name="csrf-token" content="{{ csrf_token() }}"> // 引入app.js <script src="js/app.js"></script> // 監聽並輸出 <script> // ’user1'是頻道,‘ExampleEvent’ 是監聽的事件(這是事件的類名,你也可以根據你的需要自定義) window.Echo.channel('user1') .listen('ExampleEvent', (e) => { console.log(e); }); </script>
3.開始准備事件,在對應的頻道上進行廣播
創建一個ExampleEvent事件
php artisan make:event ExampleEvent
這時在 App/Events 目錄下面會創建一個叫做 ExampleEvent.php 的事件類
事件類繼承於 ShouldBroadcast 接口
class ExampleEvent implements ShouldBroadcast
找到 broadcastOn 函數,在對應的頻道上進行廣播
// user1就是頻道 public function broadcastOn() { return new Channel('user1'); //return new PrivateChannel('channel-name'); } // 觸發事件時返回的數據 public function broadcastWith() { return [ 'data' => 'success!' ]; }
現在添加一條路由用來測試,這里也可以通過控制器去發送,相關看事件文檔
Route::get('user1', function(){ broadcast(new \App\Events\ExampleEvent); });
現在啟動監聽事件隊列
php artisan queue:listen --tries=1
現在我們可以開始測試,先打開首頁,如果你定義了其他路由自行打開,我就默認的歡迎頁面
如果看到下面頁面 恭喜你已經和服務器連接上了
客戶端運行時的狀態
服務端運行時的狀態
現在我們打開事件路由廣播一條消息,打開另一個頁面訪問 /user1,如果你設定了控制器訪問對應的路由就是了,訪問以后是空白不必緊張,我們先在終端看看隊列,如果什么都沒有輸出,自行檢查redis相關配置,以及查看redis庫內是否有數據。正確會看到下面圖,刷新一次頁面會出現一條
如果正常就可以略過這一步了,基本都是5.8版本的問題,其他也沒測試,我們先看看服務端顯示什么
頻道自動加了前綴
找到config/database.php配置文件
'options' => [ 'cluster' => env('REDIS_CLUSTER', 'predis'), // 刪掉這一行或是注釋掉 'prefix' => Str::slug(env('APP_NAME', 'laravel'), '_').'_database_', ],
然后我們再次重新啟動服務和隊列,刷新兩個頁面
就可以正常接收消息了
為什么會自動發送 2,3,因為這是 Engine .io協議
數據包編碼 | 命令 | 含義 |
0 | open | 在打開新傳輸時從服務器發送(重新檢查) |
1 | close | 請求關閉此傳輸,但不關閉連接本身。 |
2 | ping | 由客戶端發送。服務器應該用包含相同數據的乓包應答 示例1.客戶端發送:2probe 2.服務器發送:3probe |
3 | pong | 由服務器發送以響應ping數據包 |
4 | message | 實際消息,客戶端和服務器應該使用數據調用它們的回調。 實施例1 服務器發送:4HelloWorld客戶端接收並調用回調socket.on('message',function(data){console.log(data);}); 實施例2 客戶端發送:4HelloWorld服務器接收並調用回調socket.on('message',function(data){console.log(data);}) |
5 | upgrade | 在engine.io切換傳輸之前,它測試,如果服務器和客戶端可以通過這個傳輸進行通信。如果此測試成功,客戶端發送升級數據包,請求服務器刷新其在舊傳輸上的緩存並切換到新傳輸。 |
6 | noop | noop數據包。主要用於在接收到傳入WebSocket連接時強制輪詢周期。 |