站長資訊網
最全最豐富的資訊網站

Laravel 之 廣播 模塊詳解

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

推薦:《laravel教程》

簡介

廣播是指發送方發送一條消息,訂閱頻道的各個接收方都能及時收到消息;比如 A同學寫了一篇文章,這時候 B同學在文章底下評論了,A同學在頁面上是不用刷新就能收到提示有文章被評論了,這個本質上就是A同學收到了廣播消息,這個廣播消息是由B同學評論這個動作觸發了發送廣播消息;

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

● 公共頻道public

● 私有頻道private

● 存在頻道presence

移動端訂閱了公共頻道public,會直接提示成功;私有頻道private和存在頻道presence在進行訂閱的過程中,會向服務器端發送權限驗證,看是不是有權限可以訂閱該頻道;私有頻道private和存在頻道presence的區別在于,私有頻道private能夠接收其他成員發送的消息,而存在頻道presence除此之外,還能夠在用戶的加入與離開時接收信息;

廣播適合以下場景(此小部分摘自基于 Pusher 驅動的 Laravel 事件廣播(上)):

● 通知(Notification) 或 信號(Signal)

通知是最簡單的示例,也最經常用到。信號也可看作是通知的一種展現形式,只不過信號沒有UI而已。

● Activity Streams

Activity Streams(feeds)是社交網絡的核心。如微信朋友圈的點贊和評論,A可以實時看到B的點贊,B可以實時看到A的評論。

● 聊天

聊天信息的實時顯示

模塊組成

Laravel 之 廣播 模塊詳解

Demo

日志驅動

配置

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

廣播

直接調用

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

因為是日志驅動,所以廣播內容會寫到框架配置的日志文件中,輸出消息如下所示

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

監聽事件廣播

這種調用方式,是當實現ShouldBroadcast接口的事件被觸發時,則會進行廣播操作;(同時,還有一個接口叫ShouldBroadcastNow,與ShouldBroadcast接口的不同在于,將實現ShouldBroadcastNow接口的事件放入隊列中時,會被放入叫sync的隊列中)

舉個例子,

第一步,IlluminateAuthEventsLogin事件是用戶登錄成功后會觸發的事件,略作改動,讓其實現廣播功能;

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

第二步,注冊事件監聽;在app/Providers/EventServiceProvider.php中修改:

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

文件app/Listeners/UserLogin.php粗糙地實現了一下:

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

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

1.直接事件觸發

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

2.幫助函數broadcast,間接觸發事件

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

3.廣播管理類,間接觸發事件,直接廣播

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

4.廣播管理類,間接觸發事件,放入隊列

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

Pusher驅動

Pusher是一個第三方服務,服務器發送廣播時,會向Pusher發送請求,再通過Pusher與瀏覽器或移動端保持的長連接進行數據交互;

配置

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

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

準備工作

事件監聽

后臺的事件監聽還是采用"日志驅動"部分的登錄例子;

前端

前端頁面引入以下代碼:

<script src="https://js.pusher.com/4.1/pusher.min.js"></script> <script> // 打開 Pusher 的調試日志 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>

如果訂閱的是公共頻道,則不會向服務器端請求權限檢查;如果是私有頻道(頻道名是以private-開頭)或存在頻道(頻道名是以presence-開頭),則會發出權限檢查請求;對應的后端需要定義私有頻道和存在頻道的權限;

頻道權限定義

頻道的權限定義是在routes/channels.php里;此處筆者為first-channel頻道定義權限回調函數:

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

有讀者會疑問,前端頁面訂閱的頻道不是private-first-channel嗎?怎么后端只定義first-channel頻道的權限呢?那是因為,后端定義的頻道假設是A,那么在Pusher及瀏覽器端或移動端傳遞的私有頻道名為private-A,存在頻道則會是presence-A;

廣播

直接廣播

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

間接廣播

參考“日志驅動”提及的間接廣播方式;

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

1.事件使用IlluminateBroadcastingInteractsWithSockets trait;

2.前端發送過來的請求頭部要攜帶X-Socket-ID信息;

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

Redis驅動

配置

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

廣播

原理是同樣在后端部署一個Socket.IO服務器,Laravel框架會發布消息到Socket.IO服務器上,由Socket.IO服務器同瀏覽器端或者移動端保持長連接;

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

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久精品国产亚洲香蕉| 国产精品乱码一区二区三区 | 亚洲av日韩av天堂影片精品| 日韩精品亚洲专区在线观看| 亚洲免费日韩无码系列| 麻豆国产VA免费精品高清在线 | 日韩视频一区二区| 日韩av在线播放| 国产精品成人扳**a毛片| 国产精品国产亚洲区艳妇糸列短篇| 精品成人乱色一区二区| 97久久精品亚洲中文字幕无码| 久久久精品人妻一区二区三区 | 国产精品一区电影| 国内精品videofree720| 国产欧美精品123区发布| 亚洲Av永久无码精品黑人| 2017国产精品自拍| 国产chinesehd精品酒店| 亚洲一区二区三区国产精品无码| 精品深夜AV无码一区二区| 亚洲国产综合91精品麻豆| 亚洲AV无码久久精品成人| 国产精品天天看天天狠| 亚洲精品无码久久久久去q| 日韩精品无码免费专区午夜不卡 | 国产偷窥熟女精品视频大全| 国产乱码精品一区二区三区四川人 | 亚洲av产在线精品亚洲第一站 | 精品久久久久久中文字幕无碍| 四虎国产精品免费久久| 日韩精品人妻一区二区三区四区| 国产精品久久久久蜜芽| 久久国产精品77777| 国产精品免费大片| 亚洲欧洲日韩国产| 亚洲欧洲日本精品| 久久久久精品国产亚洲AV无码| 7m精品福利视频导航| 国产精品videossexohd| 久久精品国产免费一区|