本文是基於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 StreamsActivity Streams(feeds)是社群網路的核心。如微信朋友圈的點讚和評論,A可以即時看到B的點贊,B可以即時看到A的評論。 ● 聊天聊天訊息的即時顯示模組組成
Demo
日誌驅動程式設定
.env檔案修改或新增一行:BROADCAST_DRIVER=log;
廣播直接呼叫
$manager = app(Illuminate\Broadcasting\BroadcastManager::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的佇列)
舉個例子, 第一步,Illuminate\Auth\Events\Login事件是使用者登入成功後會觸發的事件,略作改動,讓其實現廣播功能;
class Login implements ShouldBroadcast { ...... // 定义事件被触发时,广播频道;此处定义名为 first-channel 的私有频道 public function broadcastOn() { return [ new PrivateChannel('first-channel'), ]; } // 自定义广播名称;如果方法未定义,默认以类名为事件名,此处的默认值是 Illuminate\Auth\Events\Login public function broadcastAs() { return 'login'; } }
第二步,註冊事件監聽;在app/Providers/EventServiceProvider.php中修改:
protected $listen = [ ...... 'Illuminate\Auth\Events\Login' => [ 'App\Listeners\UserLogin', ], ];
檔案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 Illuminate\Auth\Events\Login($user, true));
2.幫助函數broadcast,間接觸發事件broadcast(new Illuminate\Auth\Events\Login($user, true));
$manager = app(Illuminate\Broadcasting\BroadcastManager::class); $manager->event(new Illuminate\Auth\Events\Login($user, true));
4.廣播管理類,間接觸發事件,放入隊列$manager = app(Illuminate\Broadcasting\BroadcastManager::class);
$manager->queue(new Illuminate\Auth\Events\Login($user, true));
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>
Broadcast::channel('first-channel', function ($user) { return (int) $user->id === 1; });
$manager = app(Illuminate\Broadcasting\BroadcastManager::class); $driver = $manager->connection(); // socket 参数是广播私有频道时排除的 socket, 每个浏览器端或者移动端在建立 websocket 时都会被分配一个 socket_id $driver->broadcast(['private-first-channel'], 'login', ['user' => ['name' => 'hello'], 'socket' => '5395.4377611']);
如果要發送排我廣播(也就是除了目前請求的這個客戶端不收到廣播訊息),則需要以下條件:
1.事件使用Illuminate\Broadcasting\InteractsWithSockets trait;
2.前端傳送過來的請求頭要攜帶X-Socket-ID訊息;
3.事件觸發執行broadcast(new Illuminate\Auth\Events\Login($user, true)) ->toOthers();
Redis驅動程式
#設定
.env檔案修改或新增一行:BROADCAST_DRIVER= redis;
廣播
原理是同樣在後端部署一個Socket.IO伺服器,Laravel框架會發布訊息到Socket.IO伺服器上,由Socket.IO伺服器同瀏覽器端或行動端保持長連線;
這部分筆者尚未demo,網路入門資料還挺多的,知道原理,這部分動作上手就容易多了;
以上是Laravel 之 廣播 模組詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!