站長(zhǎng)資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

Laravel 之 廣播 模塊詳解

本文是基于Laravel 5.4版本的廣播模塊代碼進(jìn)行分析書寫;

推薦:《laravel教程》

簡(jiǎn)介

廣播是指發(fā)送方發(fā)送一條消息,訂閱頻道的各個(gè)接收方都能及時(shí)收到消息;比如 A同學(xué)寫了一篇文章,這時(shí)候 B同學(xué)在文章底下評(píng)論了,A同學(xué)在頁面上是不用刷新就能收到提示有文章被評(píng)論了,這個(gè)本質(zhì)上就是A同學(xué)收到了廣播消息,這個(gè)廣播消息是由B同學(xué)評(píng)論這個(gè)動(dòng)作觸發(fā)了發(fā)送廣播消息;

在整個(gè)廣播行為中,有一個(gè)重要的概念叫頻道channel,頻道的類型有

● 公共頻道public

● 私有頻道private

● 存在頻道presence

移動(dòng)端訂閱了公共頻道public,會(huì)直接提示成功;私有頻道private和存在頻道presence在進(jìn)行訂閱的過程中,會(huì)向服務(wù)器端發(fā)送權(quán)限驗(yàn)證,看是不是有權(quán)限可以訂閱該頻道;私有頻道private和存在頻道presence的區(qū)別在于,私有頻道private能夠接收其他成員發(fā)送的消息,而存在頻道presence除此之外,還能夠在用戶的加入與離開時(shí)接收信息;

廣播適合以下場(chǎng)景(此小部分摘自基于 Pusher 驅(qū)動(dòng)的 Laravel 事件廣播(上)):

● 通知(Notification) 或 信號(hào)(Signal)

通知是最簡(jiǎn)單的示例,也最經(jīng)常用到。信號(hào)也可看作是通知的一種展現(xiàn)形式,只不過信號(hào)沒有UI而已。

● Activity Streams

Activity Streams(feeds)是社交網(wǎng)絡(luò)的核心。如微信朋友圈的點(diǎn)贊和評(píng)論,A可以實(shí)時(shí)看到B的點(diǎn)贊,B可以實(shí)時(shí)看到A的評(píng)論。

● 聊天

聊天信息的實(shí)時(shí)顯示

模塊組成

Laravel 之 廣播 模塊詳解

Demo

日志驅(qū)動(dòng)

配置

.env文件修改或添加一行:BROADCAST_DRIVER=log;

廣播

直接調(diào)用

 $manager = app(IlluminateBroadcastingBroadcastManager::class);  $driver = $manager->connection();  // 第一個(gè)參數(shù)是頻道名,第二個(gè)參數(shù)是事件名,第三個(gè)參數(shù)是廣播內(nèi)容  $driver->broadcast(['channel_1', 'channel_2'], 'login', ['message' => 'hello world']);

因?yàn)槭侨罩掘?qū)動(dòng),所以廣播內(nèi)容會(huì)寫到框架配置的日志文件中,輸出消息如下所示

[2017-08-18 20:45:49] local.INFO: Broadcasting [login] on channels [channel_1, channel_2] with payload: {     "message": "hello world" }

監(jiān)聽事件廣播

這種調(diào)用方式,是當(dāng)實(shí)現(xiàn)ShouldBroadcast接口的事件被觸發(fā)時(shí),則會(huì)進(jìn)行廣播操作;(同時(shí),還有一個(gè)接口叫ShouldBroadcastNow,與ShouldBroadcast接口的不同在于,將實(shí)現(xiàn)ShouldBroadcastNow接口的事件放入隊(duì)列中時(shí),會(huì)被放入叫sync的隊(duì)列中)

舉個(gè)例子,

第一步,IlluminateAuthEventsLogin事件是用戶登錄成功后會(huì)觸發(fā)的事件,略作改動(dòng),讓其實(shí)現(xiàn)廣播功能;

class Login implements ShouldBroadcast {     ......          // 定義事件被觸發(fā)時(shí),廣播頻道;此處定義名為 first-channel 的私有頻道     public function broadcastOn() {         return [             new PrivateChannel('first-channel'),         ];     }          // 自定義廣播名稱;如果方法未定義,默認(rèn)以類名為事件名,此處的默認(rèn)值是 IlluminateAuthEventsLogin     public function broadcastAs() {         return 'login';     } }

第二步,注冊(cè)事件監(jiān)聽;在app/Providers/EventServiceProvider.php中修改:

protected $listen = [    ......    'IlluminateAuthEventsLogin' => [         'AppListenersUserLogin',    ], ];

文件app/Listeners/UserLogin.php粗糙地實(shí)現(xiàn)了一下:

class UserLogin {     public function __construct() {}          public function handle(Login $event){         Log::info('Do UserLogin Listener: I was Login');     } }

第三步,觸發(fā)事件,發(fā)送廣播;有好幾種觸發(fā)廣播方式:

1.直接事件觸發(fā)

event(new IlluminateAuthEventsLogin($user, true));

2.幫助函數(shù)broadcast,間接觸發(fā)事件

broadcast(new IlluminateAuthEventsLogin($user, true));

3.廣播管理類,間接觸發(fā)事件,直接廣播

$manager = app(IlluminateBroadcastingBroadcastManager::class); $manager->event(new IlluminateAuthEventsLogin($user, true));

4.廣播管理類,間接觸發(fā)事件,放入隊(duì)列

$manager = app(IlluminateBroadcastingBroadcastManager::class); $manager->queue(new IlluminateAuthEventsLogin($user, true));

Pusher驅(qū)動(dòng)

Pusher是一個(gè)第三方服務(wù),服務(wù)器發(fā)送廣播時(shí),會(huì)向Pusher發(fā)送請(qǐng)求,再通過Pusher與瀏覽器或移動(dòng)端保持的長(zhǎng)連接進(jìn)行數(shù)據(jù)交互;

配置

通過Pusher官網(wǎng)注冊(cè)用戶信息,獲取屬于自已的一套密鑰信息,修改.env的配置文件;

BROADCAST_DRIVER=pusher PUSHER_APP_ID=xxxxxxxxxxxxxxxxxxxxxx PUSHER_APP_KEY=xxxxxxxxxxxxxxxxxxxxxx PUSHER_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxx

準(zhǔn)備工作

事件監(jiān)聽

后臺(tái)的事件監(jiān)聽還是采用"日志驅(qū)動(dòng)"部分的登錄例子;

前端

前端頁面引入以下代碼:

<script src="https://js.pusher.com/4.1/pusher.min.js"></script> <script> // 打開 Pusher 的調(diào)試日志 Pusher.logToConsole = true; // 定義 Pusher 變量 var pusher = new Pusher('PUSHER_APP_KEY的值', {     cluster: 'ap1',     encrypted: true }); // 定義頻道,綁定事件 var channel = pusher.subscribe('private-first-channel'); channel.bind('login', function(data) {     alert(data); }); </script>

如果訂閱的是公共頻道,則不會(huì)向服務(wù)器端請(qǐng)求權(quán)限檢查;如果是私有頻道(頻道名是以private-開頭)或存在頻道(頻道名是以presence-開頭),則會(huì)發(fā)出權(quán)限檢查請(qǐng)求;對(duì)應(yīng)的后端需要定義私有頻道和存在頻道的權(quán)限;

頻道權(quán)限定義

頻道的權(quán)限定義是在routes/channels.php里;此處筆者為first-channel頻道定義權(quán)限回調(diào)函數(shù):

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

有讀者會(huì)疑問,前端頁面訂閱的頻道不是private-first-channel嗎?怎么后端只定義first-channel頻道的權(quán)限呢?那是因?yàn)椋蠖硕x的頻道假設(shè)是A,那么在Pusher及瀏覽器端或移動(dòng)端傳遞的私有頻道名為private-A,存在頻道則會(huì)是presence-A;

廣播

直接廣播

$manager = app(IlluminateBroadcastingBroadcastManager::class); $driver = $manager->connection(); // socket 參數(shù)是廣播私有頻道時(shí)排除的 socket, 每個(gè)瀏覽器端或者移動(dòng)端在建立 websocket 時(shí)都會(huì)被分配一個(gè) socket_id $driver->broadcast(['private-first-channel'], 'login', ['user' => ['name' => 'hello'], 'socket' => '5395.4377611']);

間接廣播

參考“日志驅(qū)動(dòng)”提及的間接廣播方式;

如果要發(fā)送排我廣播(也就是除了當(dāng)前請(qǐng)求的這個(gè)客戶端不收到廣播消息),則需要以下條件:

1.事件使用IlluminateBroadcastingInteractsWithSockets trait;

2.前端發(fā)送過來的請(qǐng)求頭部要攜帶X-Socket-ID信息;

3.事件觸發(fā)執(zhí)行broadcast(new IlluminateAuthEventsLogin($user, true))->toOthers();

Redis驅(qū)動(dòng)

配置

.env文件修改或添加一行:BROADCAST_DRIVER=redis;

廣播

原理是同樣在后端部署一個(gè)Socket.IO服務(wù)器,Laravel框架會(huì)發(fā)布消息到Socket.IO服務(wù)器上,由Socket.IO服務(wù)器同瀏覽器端或者移動(dòng)端保持長(zhǎng)連接;

這部分筆者尚未demo,網(wǎng)上入門資料還是挺多的,知道原理,這部分動(dòng)作上手就容易多了;

贊(0)
分享到: 更多 (0)
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
97精品伊人久久大香线蕉app| 亚洲国产精品VA在线看黑人| 国产模特众筹精品视频| av国内精品久久久久影院| 麻豆国产在线精品国偷产拍| 精品亚洲综合久久中文字幕| 国产三级精品三级在专区| 成人精品综合免费视频| 亚洲欧美日韩综合俺去了| 国产精品久久久久9999赢消| 在线视频精品一区| 精品一区二区三区| 性虎精品无码AV导航| 97久久精品无码一区二区天美| 在线精品91青草国产在线观看 | 久久这里只精品99re免费| 日韩精品无码一区二区三区AV| 精品久久久久中文字| 国产精品偷窥熟女精品视频| 亚洲七七久久精品中文国产 | 精品亚洲成a人片在线观看| 午夜精品美女自拍福到在线| 久久久无码精品国产一区| 久久国产精品麻豆映画| 老司机国内精品久久久久| 国内精品久久久久影院优| 华人在线精品免费观看| 国产女人精品视频国产灰线| 精品九九久久国内精品| 奇米精品一区二区三区在线观看| 久久夜色精品国产亚洲| 久久精品国产亚洲av麻豆| 久久久久人妻精品一区蜜桃| 久久99精品久久久久久国产| 日韩精品视频一区二区三区| 久久99精品久久久久久久不卡| 91精品国产自产在线老师啪| av国内精品久久久久影院| 思思久久96热在精品国产| 另类ts人妖精品影院| 国产精品JIZZ在线观看无码|