《PHP學習:Laravel構(gòu)建即時應(yīng)用的一種實現(xiàn)方法詳解》要點:
本文介紹了PHP學習:Laravel構(gòu)建即時應(yīng)用的一種實現(xiàn)方法詳解,希望對您有用。如果有疑問,可以聯(lián)系我們。
PHP實戰(zhàn)即時交互的應(yīng)用
PHP實戰(zhàn)大家應(yīng)該都有所體會,在現(xiàn)代的 Web 應(yīng)用中很多場景都需要運用到即時通訊,比如說最常見的支付回調(diào),與三方登錄.這些業(yè)務(wù)場景都基本需要遵循以下流程:
PHP實戰(zhàn)在過去,為了實現(xiàn)這種即時通訊,能讓客戶端正確響應(yīng)處理結(jié)果,最為常用的技術(shù)就是輪詢,因為 HTTP 協(xié)議的單向性,客戶端只能一遍一遍的主動詢問服務(wù)端的處理結(jié)果.這種方式有顯見的缺陷,占用服務(wù)端資源不說,還不能實時獲得服務(wù)端處理結(jié)果.
PHP實戰(zhàn)現(xiàn)在,我們可以使用 WebSocket 協(xié)議來處理實時交互,它是一種雙向協(xié)議,允許服務(wù)端主動推送信息到客戶端.本篇我們將借助 Laravel 強大的事件系統(tǒng)來構(gòu)建實時的交互.你將需要用到以下知識:
PHP實戰(zhàn)Redis
PHP實戰(zhàn)在開始之前,我們需要開啟一個 redis 服務(wù),并在 Laravel 應(yīng)用中進行配置啟用,因為在整個流程中,我們需要借助 redis 的訂閱和發(fā)布機制來實現(xiàn)即時通訊.
PHP實戰(zhàn)Redis 是一個開源高效的鍵值對存儲系統(tǒng).它通常作為一個數(shù)據(jù)結(jié)構(gòu)服務(wù)器來存儲鍵值對,它可以支持字符串,散列,列表,集合和有序結(jié)合.在 Laravel 中使用 Redis 你需用通過 Composer 來安裝 predis/predis 包文件.
PHP實戰(zhàn)配置
PHP實戰(zhàn)Redis 在應(yīng)用中的配置文件存儲在 config/database.php,在這個文件中,你可以看到一個包含了 Redis 服務(wù)信息的 redis 數(shù)組:
PHP實戰(zhàn) 'redis' => [ 'cluster' => false, 'default' => [ 'host' => '127.0.0.1', 'port' => 6379, 'database' => 0, ], ]
PHP實戰(zhàn)如果你修改了 redis 服務(wù)的端口,請保持配置文件中的端口一致.
PHP實戰(zhàn)Laravel Event
PHP實戰(zhàn)這里我們需要借助 Laravel 強大的事件廣播能力:
PHP實戰(zhàn)廣播事件
PHP實戰(zhàn)很多現(xiàn)代化的應(yīng)用中,會使用 Web Sockets 來實現(xiàn)實時交互的用戶接口.當一些數(shù)據(jù)在服務(wù)端變更時,一條消息會通過 WebSocket 連接來傳遞到客戶端進行處理.
PHP實戰(zhàn)為了幫助你構(gòu)建這種類型的應(yīng)用.Laravel 使通過 WebSocket 連接進行廣播事件變的非常簡單.Laravel 允許你廣播事件來共享事件的名稱到你的服務(wù)端和客戶端的 JavaScript 框架.
PHP實戰(zhàn)配置
PHP實戰(zhàn)所有的事件廣播配置選項都被存儲在 config/broadcasting.php 配置文件中.Laravel 附帶了幾種可用的驅(qū)動如 Pusher,Redis,和 Log,我們將使用 Redis 作為廣播驅(qū)動,這里需要依賴 predis/predis 類庫.
PHP實戰(zhàn)由于默認的廣播驅(qū)動使用的是 pusher,所以我們需要在 .env 文件中設(shè)置 BROADCAST_DRIVER=redis
.
PHP實戰(zhàn)我們創(chuàng)建一個 WechatLoginedEvent 事件類用來在用戶掃描微信登錄后進行廣播:
PHP實戰(zhàn) <?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 'wechat.login'; } }
PHP實戰(zhàn)其中你需要注意 broadcastOn 方法應(yīng)返回一個數(shù)組,它表示所需廣播的頻道,而 broadcastAs 返回的是一個字符串,它表示廣播所觸發(fā)的事件,Laravel 默認的是返回事件類的全類名,這里是 App\Events\WechatLoginedEvent.
PHP實戰(zhàn)最重要的是你需要手動的讓該類實現(xiàn) ShouldBroadcast 契約.Laravel 在生成事件時,已經(jīng)自動添加了該命名空間,該契約只約束 broadcastOn 方法.
PHP實戰(zhàn)事件完成接下來就是觸發(fā)事件了,簡單的一行代碼就可以:
PHP實戰(zhàn) event(new WechatLoginedEvent($token, $channel));
PHP實戰(zhàn)這個操作會自動的觸發(fā)事件的執(zhí)行并將信息廣播出去.該廣播操作底層借助了 redis 的訂閱和發(fā)布機制.
PHP實戰(zhàn)RedisBroadcaster 會將事件中的允許公開訪問的數(shù)據(jù)通過給定的頻道發(fā)布出去.如果你想對公開的數(shù)據(jù)擁有更多的控制,你可以在事件中添加 broadcastWith 方法,它應(yīng)該返回一個數(shù)組:
PHP實戰(zhàn) /** * Get the data to broadcast. * * @return array */ public function broadcastWith() { return ['user' => $this->user->id]; }
PHP實戰(zhàn)Node.js 和 Socket.io
PHP實戰(zhàn)對于發(fā)布出去的信息,我們需要一個服務(wù)來對接,讓其能對 redis 的發(fā)布能夠進行訂閱,并且能把信息以 WebSocket 協(xié)議轉(zhuǎn)發(fā)出去,這里我們可以借用 Node.js 和 socket.io 來非常方便的構(gòu)建這個服務(wù):
PHP實戰(zhàn) // server.js var app = require('http').createServer(handler); var io = require('socket.io')(app); var Redis = require('ioredis'); var redis = new Redis(); app.listen(6001, function () { console.log('Server is running!') ; }); function handler(req, res) { res.writeHead(200); res.end(''); } io.on('connection', function (socket) { socket.on('message', function (message) { console.log(message) }) socket.on('disconnect', function () { console.log('user disconnect') }) }); redis.psubscribe('*', function (err, count) { }); redis.on('pmessage', function (subscrbed, channel, message) { message = JSON.parse(message); io.emit(channel + ':' + message.event, message.data); });
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/198.html