首頁  >  文章  >  php框架  >  Laravel 即時應用的一種實作方式

Laravel 即時應用的一種實作方式

藏色散人
藏色散人轉載
2019-10-21 13:29:443028瀏覽

即時互動的應用

在現代的 Web 應用中很多場景都需要運用到即時通訊,比如說最常見的支付回調,與三方登入。這些業務場景基本上都需要遵循以下流程:

● 客戶端觸發相關業務,並產生第三方應用的操作(例如付款)

● 客戶端等待服務端回應結果(用戶完成第三方應用程式的作業)

● 第三方應用通知服務端處理結果(支付完成)

● 服務端通知用戶端處理結果

● 用戶端依據結果做出回饋(跳到付款成功頁面)

在過去,為了實現這種即時通訊,能讓客戶端正確回應處理結果,最常用的技術就是輪詢,因為HTTP 協定的單向性,客戶端只能一再的主動詢問服務端的處理結果。這種方式有顯見的缺陷,佔用服務端資源不說,還不能即時獲得服務端處理結果。

現在,我們可以使用 WebSocket 協議來處理即時交互,它是一種雙向協議,允許服務端主動推送訊息到客戶端。本篇我們將藉助 Laravel 強大的事件系統來建構即時的互動。你將需要使用以下知識:

●  Laravel Event

● Redis

●● Socket.io

##● Node.js

#Redis

在開始之前,我們需要開啟一個redis 服務,並在Laravel 應用程式中進行設定啟用,因為在整個流程中,我們需要藉助redis 的訂閱和發布機制來實現即時通訊。

Redis 是一個開源高效的鍵值對儲存系統。它通常作為一個資料結構伺服器來儲存鍵值對,它可以支援字串,散列,列表,集合和有序結合。在 Laravel 中使用 Redis 你需要用透過 Composer 來安裝 predis/predis 套件檔案。

設定

Redis 在應用程式中的設定檔儲存在config/database.php,在這個檔案中,你可以看到一個包含了Redis 服務資訊的redis 數組:

'redis' => [
  'cluster' => false,
  'default' => [
    'host' => '127.0.0.1',
    'port' => 6379,
    'database' => 0,
  ],
]

如果你修改了redis 服務的端口,請保持設定檔中的端口一致。

Laravel Event##這裡我們需要藉助Laravel 強大的事件廣播能力:

廣播事件

很多現代化的應用程式中,會使用Web Sockets 來實現即時互動的使用者介面。當一些資料在服務端變更時,一則訊息會透過 WebSocket 連線來傳遞到客戶端進行處理。

為了幫助你建立這種類型的應用程式。 Laravel 讓透過 WebSocket 連線進行廣播事件變的非常簡單。 Laravel 允許你廣播事件來共享事件的名稱到你的服務端和客戶端的 JavaScript 框架。

設定

所有的事件廣播設定選項都會儲存在 config/broadcasting.php 設定檔中。 Laravel 附帶了幾種可用的驅動如 Pusher,Redis,和 Log,我們將使用 Redis 作為廣播驅動,這裡需要依賴 predis/predis 類別庫。

由於預設的廣播驅動使用的是 pusher,所以我們需要在 .env 檔案中設定 BROADCAST_DRIVER=redis。

我們建立一個WechatLoginedEvent 事件類別用來在使用者掃描微信登入後進行廣播:

<?php
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class WechatLoginedEvent extends Event implements ShouldBroadcast
{
    use SerializesModels;
    public $token;
    protected $channel;
    /**
     * Create a new event instance.
     *
     * @param  string $token
     * @param  string $channel
     * @return void
     */
    public function __construct($token, $channel)
    {
        $this->token = $token;
        $this->channel = $channel;
    }
    /**
     * Get the channels the event should be broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return [$this->channel];
    }
    /**
     * Get the name the event should be broadcast on.
     *
     * @return string
     */
    public function broadcastAs()
    {
        return &#39;wechat.login&#39;;
    }
}

其中你需要注意broadcastOn 方法應傳回一個數組,它表示所需廣播的頻道,而broadcastAs 回傳的是一個字串,它表示廣播所觸發的事件,Laravel 預設的是傳回事件類別的全類名,這裡是App\Events\WechatLoginedEvent.

最重要的是你需要手動的讓該類別實作ShouldBroadcast 契約。 Laravel 在產生事件時,已自動新增了該命名空間,該契約只約束 broadcastOn 方法。

事件完成接下來就是觸發事件了,簡單的一行程式碼就可以:

event(new WechatLoginedEvent($token, $channel));

這個操作會自動的觸發事件的執行並將訊息廣播出去。此廣播操作底層借助了 redis 的訂閱和發布機制。 RedisBroadcaster 會將事件中的允許公開存取的資料透過給定的頻道發佈出去。如果你想對公開的資料有更多的控制,你可以在事件中加入broadcastWith 方法,它應該回傳一個陣列:

/**
 * Get the data to broadcast.
 *
 * @return array
 */
 public function broadcastWith() 
 {
   return [&#39;user&#39; => $this->user->id];
 }

Node.js 和Socket.io

#對於發佈出去的信息,我們需要一個服務來對接,讓其能對redis 的發布能夠進行訂閱,並且能把信息以WebSocket 協議轉發出去,這裡我們可以藉用Node.js 和socket.io 來非常方便的構建這個服務:

// server.js
var app = require(&#39;http&#39;).createServer(handler);
var io = require(&#39;socket.io&#39;)(app);
var Redis = require(&#39;ioredis&#39;);
var redis = new Redis();
app.listen(6001, function () {
  console.log(&#39;Server is running!&#39;) ;
});
function handler(req, res) {
  res.writeHead(200);
  res.end(&#39;&#39;);
}
io.on(&#39;connection&#39;, function (socket) {
  socket.on(&#39;message&#39;, function (message) {
    console.log(message)
  })
  socket.on(&#39;disconnect&#39;, function () {
    console.log(&#39;user disconnect&#39;)
  })
});
redis.psubscribe(&#39;*&#39;, function (err, count) {
});
redis.on(&#39;pmessage&#39;, function (subscrbed, channel, message) {
  message = JSON.parse(message);
  io.emit(channel + &#39;:&#39; + message.event, message.data);
});

這裡我們使用Node.js 引入socket.io 服務端並監聽6001 端口,借用redis 的psubscribe 指令使用通配符來快速的批量訂閱,接著在消息觸發時將訊息透過WebSocket 轉發出去。

Socket.io 用戶端

在web 前端,我們需要引入Socket.io 用戶端開啟與服務端6001 連接埠的通訊,並訂閱頻道事件:

// client.js
let io = require(&#39;socket.io-client&#39;)
var socket = io(&#39;:6001&#39;)
      socket.on($channel + &#39;:wechat.login&#39;, (data) => {
        socket.close()
        // save user token and redirect to dashboard
})

至此整個通訊閉環結束,開發流程看起來就是這樣的:

● 在Laravel 中建構一個支援廣播通知的事件

● 設定需要進行廣播的頻道及事件名稱

● 將廣播設定為使用redis 驅動程式

#################################################################### ● 提供一個持續的服務用於訂閱redis 的發布,及將發佈內容透過WebSocket 協定推送到客戶端######● 客戶端開啟服務端WebSocket 隧道,並對事件進行訂閱,根據指定事件的推送進行響應。 ######更多Laravel相關技術文章,請造訪###Laravel框架入門教學###專欄進行學習! ###

以上是Laravel 即時應用的一種實作方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除