您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何通過laravel-echo主動向服務端發送消息以及實現在線狀態管理 ,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
之前在網上翻了半天,也沒有找到關于如何 通過 laravel-echo
主動發送消息 和 在 laravel-websockets
中自定義控制器 的文章或教程。無奈之下只能翻 laravel-echo
和 laravel-websockets
的源碼了,小有收獲。在此為有需要的朋友指個方向,少踩一個坑。
在使用 laravel-echo
時,網頁想主動向服務器發送消息該怎么做呢?首先,最簡單的就是 Ajax
異步請求了,寫起來很容易。還有一種方式就是通過 websocket
了,既然已經建立了 socket 連接,我們何不利用他來進行雙向通信呢!
如何使用 laravel-echo
通過 websocket
進行反向通信(這里的「反向」指從網頁向服務器發送消息)。
網頁默認連接的 websocket 地址是 http://<your.host>:<wsPort>/app/<key>
。url 中的 /app/
部分是 pusher
中規定的,目前還無法修改。<key> 指實例化 Echo
時的參數「key」,同時也是.env
文件中的 PUSHER_APP_KEY
環境變量。服務器端控制器是 laravel-websockets
已經定義好的控制器:BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler
。現在我們要實現自己的控制器,來做在線狀態管理,所以就需要改變網頁默認連接的 websocket 地址和后臺控制器。
打開 resources/views/hellow.blade.php
視圖文件,在初始化 Echo
中的參數部分加入 wsPath
變量。此時 websocket 監聽的地址就會變為 http://<your.host>:<wsPort><wsPath>/app/<key>
。
window.Echo = new Echo({broadcaster: 'pusher',key: 'joker',// 在 socket 鏈接中設置 url 路徑wsPath: '/liam/hao',wsHost: location.hostname,wsPort: 2020,forceTLS: false,});
注意:
wsPath
變量一定要用 “/” 開頭,否則會報錯的
技巧:這里再提一個小知識點吧,
pusher
默認會在連接 websocket 時發送http://sockjs.pusher.com/pusher
請求,如果看著別扭(我不喜歡在網站中出現自己控制范圍外的事情),可以在初始化Echo
的參數中加一個enabledTransports
變量,值是['ws', 'wss']
。這樣pusher
就會將http://sockjs.pusher.com/pusher
請求替換為你自己的 websocket 連接地址:window.Echo = new Echo({..// 加上這個參數后,就不會再向 http://sockjs.pusher.com/pusher 發送請求了enabledTransports: ['ws', 'wss'],});
因為前端改變了監聽地址。對應的后端,也需要新增一個對應的路由。我們打開 routes/web.php
文件,加入以下新路由:
Route::get('/login', function () {return view('login');});// 這個是 laravel-websockets 提供的門面方法,用來注冊自定義的 websocekt 路由// WebSocketsRouter 綁定的實際對象是 BeyondCode\LaravelWebSockets\Server\Router 有興趣的可以瞅瞅\BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter::webSocket('/liam/hao/app/{appKey}', \App\Http\Controllers\MyWebsocketHandler::class);
上面的路由中綁定了一個 App\Http\Controllers\MyWebsocketHandler
類,現在我們就來實現這個類:
> php artisan make:controller MyWebsocketHandler Controller created successfully.
執行上面的命令后,我們會在 app/Http/Controllers
文件夾中找到 MyWebsocketHandler.php
文件,我們來進行一些修改:
<?phpnamespace App\Http\Controllers;use BeyondCode\LaravelWebSockets\WebSockets\Messages\PusherMessageFactory;use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler;use Ratchet\ConnectionInterface;use Ratchet\RFC6455\Messaging\MessageInterface;// 注意這里要繼承自 WebSocketHandlerclass MyWebsocketHandler extends WebSocketHandler{public function onMessage(ConnectionInterface $connection, MessageInterface $message){var_dump(json_decode($message->getPayload()));$message = PusherMessageFactory::createForMessage($message, $connection, $this->channelManager);$message->respond();}public function onClose(ConnectionInterface $connection){$this->channelManager->removeFromAllChannels($connection);var_dump('close');}}
好了,我們現在來小測一下,看看新的路由有沒有生效。重啟 laravel-websockets
的 http 服務。打開瀏覽器的開發者工具,然后刷新頁面。如果像下圖一樣,在命令行終端里看到了我們 var_dump()
的數據,那就說明新的路由和控制器已經連通了:
注意:MyWebsocketHandler 并不是一般的 Controller,他需要繼承自
BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler
。如果你需要控制更多邏輯,可直接實現Ratchet\WebSocket\MessageComponentInterface
接口,并自己實現onOpen()
、onClose()
、onMessage()
等方法。
重點來了哈,雖說是重點,但代碼很簡單:
Echo.channel('abcdefg.'+uuid).listen('LoginedEvent', (e) => {console.log(e);var session_id = e.session_id;location.href = location.origin+'/hello?session_id='+session_id;});// 我們在這里放置一個定時器,每三秒鐘向服務器發送一條數據setInterval(function(){// 這里新增一個向服務端發送消息的方法// 第一個參數是事件名,這個可以隨意寫,不需要與 Laravel 中做對應// 第二個參數是具體數據,這個就更隨意了Echo.connector.pusher.send_event('hi_girl', {my_name: 'LiamHao',my_height: 180,});}, 3000);
是不是很簡單,我們再來小測一下,看看服務端接收到的數據是什么樣子的:
后端已經接收到數據了。做到這里,想必有些基礎的朋友應該已經可以做自己想做的事情了。
這里我們就不做太復雜了數據庫操作了,還是老樣子,以最簡單的方式,用 緩存 做記錄吧。我們在 App\Http\Controllers\MyWebsocketHandler
的 onMessage()
和 onClose()
方法中分別加入記錄狀態的代碼:
public function onMessage(ConnectionInterface $connection, MessageInterface $message){var_dump(json_decode($message->getPayload()));// 每當收到消息時,設置當前連接狀態為“在線”,60 秒后過期\Cache::put('socekt-status', ['socket_id' => $connection->socketId,'status' => '在線',], 60);$message = PusherMessageFactory::createForMessage($message, $connection, $this->channelManager);$message->respond();}public function onClose(ConnectionInterface $connection){$this->channelManager->removeFromAllChannels($connection);var_dump('close');// 瀏覽器主動斷開連接時,設置當前連接狀態為“離線”,不設置過期時間\Cache::put('socekt-status', ['socket_id' => $connection->socketId,'status' => '離線',]);}
然后修改下 resources/views/login.blade.php
視圖文件,在頁面中顯示連接的狀態:
<body><input type="text" name="username"><input type="text" name="password"><button>登陸</button><!-- 我們在這里簡單的展示一下連接的狀態 --><h2>Websocket 連接列表</h2><!-- 用 blade 模板語法渲染數據,簡單的打印下數據 --><pre>{{ var_export(\Cache::get('socekt-status')) }}</pre></body>
大功告成,我們來看下效果。先打開 http://<your.host>/login
頁面,此時未顯示任何內容。這是正常的,因為 Cache
中還沒有記錄任何信息。接下來再打開 http://<your.host>/hello
頁面,看下瀏覽器開發者工具中 websocket 已連接成功。下面見證奇跡的時刻到了,我們再將 http://<your.host>/login
頁面刷新一次,此時會看到 Cache
中記錄的在線狀態信息:
我們再來試下斷開 websocekt 連接時,是否會顯示離線。將 http://<your.host>/hello
頁面直接關閉,也就是點標簽頁上的「叉子」。再刷新下 http://<your.host>/login
頁面:
上述內容就是如何通過laravel-echo主動向服務端發送消息以及實現在線狀態管理 ,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。