laravel11广播
大约 4 分钟
pusher驱动
https://github.com/tlaverdure/laravel-echo-server
docker方式
创建一个 docker-compose.yml
文件
services:
echo:
image: oanhnn/laravel-echo-server
ports:
- 6001:6001
volumes:
- ./echo:/app
environment:
- LARAVEL_ECHO_SERVER_GENERATE_CONFIG=true
第一次启动会创建一个./echo/laravel-echo-server.json
文件
**authHost:**这里是laravel程序的域名地址 (如果使用了私有或授权广播,需要填写这个值)
authEndpoint: laravel 默认的广播地址(可保持不变)
redis.host: 没有 https://
前缀
{
"authHost": "http://localhost",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "df520990040eb943",
"key": "7330b69b1df85b1e65c6b2034745a690"
}
],
"database": "redis",
"databaseConfig": {
"redis": {
"host": "192.168.101.26",
"port": 6379,
"password": "admin666",
"keyPrefix": "doctor",
"options": {
"db": 1
}
},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {},
"secureOptions": 67108864,
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "*",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
本地方式
安装依赖
npm i -g laravel-echo-server
# 初始化配置文件
laravel-echo-server init
# 添加app_id
laravel-echo-server client:add <APP_ID>
# 启动服务
laravel-echo-server start
配置连接:resources/js/bootstrap.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001', //本地使用这个方式
// host: 'http://home.com:6001', // laravel-echo 是一个独立运行的使用这个方式
//可选
auth: {
headers: {
Authorization: "Bearer " + LocalStorage.get(EnumData.tokenLabel) // 登录后获得的token值,主要看怎么进行权限认证的
}
}
});
在入口html中添加
<meta name="csrf-token" content="{{ csrf_token() }}">
<script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>
// 也可以下载之后直接引入
<script src="//home.com:6001/socket.io/socket.io.js"></script>
<script src="/js/socket.io.js"></script>
示例
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ env("APP_NAME") }}</title>
<script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>
<style>
body {
font-family: 'Nunito', sans-serif;
}
</style>
@vite(["resources/css/app.css",'resources/js/app.js'])
</head>
<body class="antialiased">
<div id="app">
<router-view />
</div>
</body>
</html>
授权地址说明:
如果是将程序,redis,laravel-echo-server 分开部署的话,直接填写对应的域名即可。
如果是单服务器部署,以宝塔为例,如果我们绑定 :chat.cc
这样一个域名,我们在添加一个绑定,这个主要是端口的绑定这个服务,本地项目可以通过不同的端口访问不同的服务。
nginx配置
location / {
proxy_pass http://localhost:6001;
}
location /socket.io {
proxy_pass http://localhost:6001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
后端
安装依赖
composer require pusher/pusher-php-server
env配置
PUSHER_APP_ID="df520990040eb943"
PUSHER_APP_KEY="7330b69b1df85b1e65c6b2034745a690"
PUSHER_APP_SECRET=""
PUSHER_HOST=home.cc # laravel-echo 地址
PUSHER_PORT=6001 @ laravel-echo 端口
PUSHER_SCHEME="http"
PUSHER_APP_CLUSTER="mt1"
创建一个路由触发事件
Route::post("seed",[\App\Http\Controllers\Api\Openai\Index::class,"seed"]);
public function seed()
{
$message = (string)\request("message");
AssertUtils::isEmpty($message,"请输入内容");
$data =ChatMessage::create([
"uid" => \request()->user()->id,
"content" => $message,
"type" => 1
]);
// 触发事件
event(new OpenaiMessage($data));
return $this->success("success",$data);
}
公共消息-channel
php artisan make:event ChatMessage
app/Events/ChatMessage.php
私有消息-
php artisan make:event FriendEvent
频道消息-
php artisan make:event GroupEvent
频道授权方式
1、session 方式授权 (默认方式)
这种方式需要在网页端登录后的用户监听私有频道的时候,私有私有频道才能进行认证。
2、sanctum 方式授权
此方式使用了jwt的方式进行的认证,当我们使用次方式进行认证的时候,我们判断用户是否登录,需要用户在header头中写道token,在路由中设置 auth:sanctum
的中间件,从而获取到用户的的登录于是,在laravel的中我们也需要使用这个方式的认证,找到:app/Providers/BroadcastServiceProvider.php
文件,设置认证方式
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes([
"middleware" => ["auth:sanctum"]
]);
require base_path('routes/channels.php');
}
}
授权
// $user: 当登录的用户信息,$id:路由传递的参数
Broadcast::channel('user.{uid}', function ($user, $uid) {
return true; // 我们可以在这里做一些判断,最后返回是 true|false 就可以
});
前端
env配置
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_APP_KEY="your-pusher-key"
PUSHER_APP_SECRET="your-pusher-secret"
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME="https"
PUSHER_APP_CLUSTER="mt1"
# 主要是下面的
VITE_APP_NAME="${APP_NAME}"
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
安装依赖
yarn add laravel-echo pusher-js
初始化配置
window.Echo = new Echo({
broadcaster: 'socket.io',//'pusher',
key: key,
host: `${host}:${port}`,//"localhost:6001",
enabledTransports: ['ws', 'wss'],
auth:{
headers:{
Authorization: 'Bearer ' + LocalStorage.get(EnumData.tokenLabel)
}
}
});
window.Pusher = Pusher;
接收公共消息
window.Echo.connector.socket.on('connect', () => { // 成功连接服务器后在接受通道消息
this.status = true;
window.Echo.channel('user.' + this.info.id) //频道的名称
.listen('UserNotice', (e) => { // 监听的事件
console.log("UserNotice:", e)
})
.error((err) => {
console.log(err);
});
});
接收私有消息
window.Echo.connector.socket.on('connect', () => { // 成功连接服务器后在接受通道消息
this.status = true;
window.Echo.private('user.' + this.info.id) // 频道的名称
.listen('UserNotice', (e) => { // 监听的事件
console.log("UserNotice:", e)
})
.error((err) => {
console.log(err);
});
});
接收频道消息
关闭连接
discontent() {
const pusher = window.Echo.constructor.pusher;
if (pusher) {
pusher.disconnect();
}
window.Echo = null;
},
是否连接
window.Echo.connector.socket.on('connect', () => {
this.status = true;
window.Echo.channel('user.' + this.info.id) //频道的名称
.listen('UserNotice', (e) => { // 监听的事件
console.log(e);
})
.error((err) => {
console.log(err);
});
});
window.Echo.connector.socket.on('connect_error', (error) => {
this.status = false;
this.discontent();
this.$Message.error("消息连接失败,请刷新浏览器重试");
});