Laravel10,Laravel广播,Laravel-echo使用
最近又想用下 Laravel 的广播,结果发现和之前的不一样了,乘着项目上线遇到的一些坑,做一下使用流程
用到得东西:
predis
socket.io-client@2.3.0
laravel-echo-server
laravel-echo
laravel-10
第一步:用到的东西都安装一下
在项目根目录执行下面
$> npm install socket.io-client@2.3.0 #版本一定要对!
$> npm install laravel-echo
$> npm install -g laravel-echo-server
$> laravel-echo-server init
? Do you want to run this server in development mode? Yes # 生产环境为 No
? Which port would you like to serve from? 6001 #服务端口
? Which database would you like to use to store presence channel members? redis #redis
? Enter the host of your Laravel authentication server. http://localhost #host
? Will you be serving on http or https? http # http
? Do you want to generate a client ID/Key for HTTP API? No #No
? Do you want to setup cross domain access to the API? Yes #我这边项目是不同的域名所以需要进行跨域
? Specify the URI that may access the API: https://xxx.com #需要跨域请求的域名
? Enter the HTTP methods that are allowed for CORS: GET, POST #方法
? Enter the HTTP headers that are allowed for CORS: Origin, Content-Type, X-Auth-Token, X-Requested-With,Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id #header
? What do you want this config to be saved as? laravel-echo-server.json
Configuration file saved. Run `laravel-echo-server start` to run server.
$> laravel-echo-server start #这个东西我们可以先不用启动
$> composer require predis/predis #安装 predis 包
第二步:开启 BroadcastServiceProvider 服务
目录:config/app.php
'providers' => [
/................../
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\BroadcastServiceProvider::class, # 这里需要打开注释
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
],
第三步:配置 .env 文件的广播驱动为 redis
BROADCAST_DRIVER=redis #这里
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=redis #广播走队列系统,所以这里也要改一下
SESSION_DRIVER=redis
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=predis # 注意这里要用 predis
REDIS_HOST=127.0.0.1 # redis 地址
REDIS_PASSWORD=null # redis 密码
REDIS_PORT=6379 # redis 端口
#下面这三个东东也要配置哦,具体说明可以看下 laravel-echo-server 的 github 文档
LARAVEL_ECHO_SERVER_REDIS_HOST=127.0.0.1 # redis 地址
LARAVEL_ECHO_SERVER_REDIS_PASSWORD=null # redis 密码
LARAVEL_ECHO_SERVER_REDIS_PORT=6379 # redis 端口
第四步:因为 Laravel 会有 redis 前缀所以我们还需要配置一下 laravel-echo-server 的配置文件,加上这个前缀
{
"authHost": "http://localhost",
"authEndpoint": "/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {
"keyPrefix": "laravel_database_" # 这里的 laravel 是根据 env 文件的 APP_NAME 变得,如果你改了 APP_NAME 那么这里也要改,举个例子:APP_NAME=Plant 那这里就是 plant_databases_
},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {
"path": "/chat" # 注意这里,如果你的服务器上面有多个 laravel-echo-server,那你肯定会遇到需要改变 socket.io 默认路径的问题,当然如果你只有一个项目那么就不需要咯
},
"secureOptions": 67108864,
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "https://xxx.com",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
第五步:打开 resource/js/bootstrap.js 修改为下面的配置
# 这里前面的内容省略啦~
import Echo from 'laravel-echo';
import io from 'socket.io-client';
window.io = io;
//
// import Pusher from 'pusher-js';
// window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname, # 这里也可以进行修改,比如我这边的服务是个单独的域名那么就可以写成 https://oooo.com
path: "/chat", # 这里的路径要和 laravel-echo-serve.json 中 socket.io 一模一样,官方默认是 /socket.io
withCredentials: false
});
接下来就是生成编译文件
$> npm run dev #本地环境执行这个
$> npm run build #生产直接生成文件
第六步:开始试验广播
$> php artisan make:event ShippingStatusUpdated
修改文件内容
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class ShippingStatusUpdated implements ShouldBroadcast # 这里需要加上这个接口
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public int $id; #public 公开数据会通过广播推到前端~
/**
* Create a new event instance.
*/
public function __construct($id) # 这里可以接受任何数据
{
$this->id = $id;
}
/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new Channel('order'), # 通道名字
];
}
public function broadcastAs(): string
{
return 'OrderUpdated'; # 监听别名
}
}
接下来就是前端页面
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<script src="build/asset/app.xxxx.js"></script> <!-- 这里需要引入 npm run build 生产的 app.xxx.js 的文件,注意这里会生成两个要引入文件比较大的那个文件 -->
</head>
<body class="antialiased">
<script>
window.onload = function () { // 为啥要用 onload 是因为 js 文件还没加载完成,就执行 window.Echo 会提示 undefined
window.Echo.channel('order') // 这里监听的是通道名字
.listen('.OrderUpdated', (e) => { // 这是监听的广播别名,事件别名
console.log(e);
});
console.log(window.Echo);
};
</script>
</body>
</html>
启动队列
php artisan queue:work
模拟执行一下,就可以收到消息了~
Route::get('/send', function () {
event(new ShippingStatusUpdated(1));
});
Nginx代理问题:
由于我这边服务器上面有多个广播服务,所以我需要修改广播的默认 path 也就是 socket.io 的默认请求 path,下面是 nginx 的配置
# 这里是 socket.io 默认的 nginx 配置
location /socket.io {
proxy_pass http://127.0.0.1:6003; #could be localhost if Echo and NginX are on the same box
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
# 当我们需要修改默认的 /socket.io 请求路由时,这里的 chat 就要和 laravel-echo-server.json 和 bootstrap.js 中的 path 相互对应,不然是走不通的,这块卡了我挺长时间,去看了 socket.io 的文档后才联想到这点。
location /chat/{
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:6006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: