先附上 github地址
https://github.com/nothing49199/laravel-echo
簡介
在很多現代 Web 應用中,WebSockets被用于實現實時更新的用戶接口。當一些數據在服務器上
被更新,通常一條消息通過 Websocket 連接被發送給客戶端處理。這為我們提供了一個更強大的、更有效的選擇來持續拉取應用的更新。
為實現的這樣的應用,Laravel 中 通過 Websocket 連接廣播事件使開發變得簡單。廣播 Laravel 事件允許你在服務端和客戶端 JavaScript 框架之間共享同一事件名
本 文檔 僅使用了 redis的廣播驅動
思路
laravel 的廣播系統和隊列系統類似,需要兩個進程協作,一個是 laravel 的 web 后臺系統,另一個是 Socket.IO 服務器系統。具體的流程是頁面加載時,網頁 js 程序 Laravel Echo 與 Socket.IO 服務器建立連接, laravel 發起通過驅動發布廣播,Socket.IO 服務器接受廣播內容,對連接的客戶端網頁推送信息,以達到網頁實時更新的目的。
配置
配置文件 config/broadcasting.php,可以直接在 .env 中配置以下代碼
BROADCAST_DRIVER=redis
廣播服務提供者
config/app.php 配置文件中 providers數組中打開注釋
App\Providers\BroadcastServiceProvider::class,
CSRF令牌
Laravel Echo需要訪問當前 Session 的 CSRF 令牌(token)
自創建的 blade視圖的 head中 加入 meta標簽
<meta name="csrf-token" content="{{ csrf_token() }}">
Redis
Redis廣播需要安裝 Predis庫
composer require predis/predis
安裝Laravel Echo
Laravel Echo是一個JavaScript庫,web端可以輕松訂閱頻道并收聽Laravel廣播的事件
通過 npm 包管理器安裝 Echo
npm install
npm install laravel-echo-server
初始化 laravel-echo-server
laravel-echo-server init
// 是否在開發模式下運行此服務器(y/n) 輸入y
? Do you want to run this server in development mode? (y/N)
// 設置服務器的端口 默認 6001 輸入 6001就可以了 或者你想要的
? Which port would you like to serve from? (6001)
// 想用的數據庫 選擇 redis
? Which database would you like to use to store presence channel members? (Use arrow keys)
? redis
sqlite
// 這里輸入 你的laravel 項目的訪問域名
? Enter the host of your Laravel authentication server. (http://localhost)
// 選擇 網絡協議 http
? Will you be serving on http or https? (Use arrow keys)
? http
https
// 您想為HTTP API生成客戶端ID/密鑰嗎 N
? Do you want to generate a client ID/Key for HTTP API? (y/N)
// 要設置對API的跨域訪問嗎?(y/n)N
Configuration file saved. Run laravel-echo-server start to run server.
設置完成后 項目根目錄 下 會生成 laravel-echo-server.json 文件 這里面就是剛才的配置
執行命令啟動 服務 出現如下 則啟動成功
laravel-echo-server start
L A R A V E L E C H O S E R V E R
version 1.4.2
? Starting server in DEV mode...
? Running at localhost on port 6001
? Channels are ready.
? Listening for http events...
? Listening for redis events...
Server ready!
頻道
頻道必須是 Channel、PrivateChannel 或 PresenceChannel 的實例。Channel 實例表示任何用戶都可以訂閱的公開頻道,而 PrivateChannels 和 PresenceChannels 則表示需要 頻道授權 的私有頻道:
創建事件
php artisan make:event PublicMessageEvent
文件生成目錄 app/Events
// 消息內容
public $message;
public function __construct(string $message)
{
$this->message = $message;
}
// 返回一個公共頻道 頻道名稱為push
public function broadcastOn()
{
return new Channel('push');
}
// Laravel 默認會使用事件的類名作為廣播名稱來廣播事件,自定義:
public function broadcastAs()
{
return 'push.message';
}
添加路由
use App\Events\PublicMessageEvent;
Route::get('/echo', function () {
return view('echo');
});
Route::get('/push/{message}', function ($message) {
broadcast(new PublicMessageEvent($message));
})
前端
安裝 laravel-echo
npm install laravel-echo
編輯 resource/js/bootstrap.js 添加如下代碼
import Echo from "laravel-echo"
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
編輯 resource/js/app.js 添加如下代碼
Echo.channel('push')
.listen('.push.message', (e) => {
alert('來了')
console.log(e);
});
創建 echo.blade.php
head 中加上
<meta name="csrf-token" content="{{ csrf_token() }}">
<script src="http://{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>
<script src="/js/app.js"></script>
編譯 js 文件
npm run watch
瀏覽器訪問 項目域名/echo
瀏覽器訪問 項目域名/push/這是一個測試廣播
echo 頁面 會自動彈出
到這 廣播 發布到公共頻道就完成了
私有頻道 PrivateChannel
創建事件
php artisan make:event PrivateMessageEvent
PrivateMessageEvent 中 寫入 以下內容
class PrivateMessageEvent implements ShouldBroadcast
{
// 消息內容
public $message;
// 用戶
public $user;
public function __construct(User $user, string $message)
{
$this->user = $user;
$this->message = $message;
}
// 創建私有頻道
public function broadcastOn()
{
return new PrivateChannel('privatePush.' . $this->user->id);
}
// //Laravel 默認會使用事件的類名作為廣播名稱來廣播事件,自定義:
// public function broadcastAs()
// {
// return 'privatePush.message';
// }
// 控制廣播數據:
public function broadcastWith()
{
return ['message' => $this->message,'status' => 'okok'];
}
}
添加發布廣播到私有頻道 觸發路由 routes/web
Route::get('/privatePush/{message}/{id}', function ($message, $id) {
$user = \App\User::find($id);
if (empty($user)) return '無此用戶';
broadcast(new PrivateMessageEvent($user, $message));
});
頻道授權
定義授權路由 routes/channel 中加入一下代碼
Broadcast::channel('privatePush.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
前端
echo.blade.php 中加入
<script>
@if(!empty(Auth::user()))
window.id = "{{Auth::user()->id}}"
@endif
</script>
app.js
Echo.private('privatePush.' + window.id)
.listen('PrivateMessageEvent', (e) => {
alert('qweqwe')
console.log(e);
});