laravel9.x + beyondcode/laravel-websockets 实现广播 + websocket
beyondcode/laravel-websockets 文档
安装 beyondcode/laravel-websockets
composer require beyondcode/laravel-websockets
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
安装 pusher-php-server
composer require pusher/pusher-php-server:7.0.2
修改.env文件
BROADCAST_DRIVER=pusher
# 这里PUSHER_APP_ID、PUSHER_APP_KEY、PUSHER_APP_SECRET随便填写
PUSHER_APP_ID=test-websockets
PUSHER_APP_KEY=qwerty
PUSHER_APP_SECRET=123456789
PUSHER_HOST=localhost
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
启动websockets
# 默认启动
php artisan websockets:serve
# 指定端口
php artisan websockets:serve --port=3030
# 指定host
php artisan websockets:serve --host=127.0.0.1
结合supervisord管理
安装客户端
npm install --save-dev laravel-echo pusher-js
npm run dev
修改 resources/js/bootstrap.js文件
// 打开注释
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
增加一条web路由
Route::get('/', function () {
return view('welcome');
});
// 发送广播
Route::get('/event', function () {
$str = \Illuminate\Support\Str::random();
broadcast(new \App\Events\Free($str));
});
welcome.blade.php文件新增
// 引入app.js文件
@vite('resources/js/app.js')
<script>
// document.addEventListener 防止提示Echo未定义
document.addEventListener("DOMContentLoaded", function (event) {
Echo.channel(`channel-free`)
.listen('Free', (e) => {
console.log('listen ok')
console.log(e.data);
});
})
</script>
Free Event 文件
<?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 Free implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $msg;
public function __construct($msg)
{
$this->msg = $msg;
}
public function broadcastOn()
{
return new Channel('channel-free');
}
public function broadcastWith ()
{
return [
'data' => $this->msg
];
}
}
自定义WebSocket处理程序
创建
MyCustomWebSocketHandler.php
文件<?php namespace App; use Illuminate\Support\Facades\Log; use Ratchet\ConnectionInterface; use Ratchet\RFC6455\Messaging\MessageInterface; use Ratchet\WebSocket\MessageComponentInterface; class MyCustomWebSocketHandler implements MessageComponentInterface { public function onOpen(ConnectionInterface $connection){ // 这里处理 返回的Error Exception thrown undefined property Ratchet\Server\IoConnection::$app错误 $socketId = sprintf('%d.%d', random_int(1, 1000000000), random_int(1, 1000000000)); $connection->socketId = $socketId; $connection->app = new \stdClass(); $connection->app->id = env('APP_NAME').'- Test'; return $connection->send('您已链接:'.now()->toDateString()); } public function onClose(ConnectionInterface $connection) { } public function onError(ConnectionInterface $connection, \Exception $e) { } public function onMessage(ConnectionInterface $connection, MessageInterface $msg) { // 接受客户端发送过来的信息 Log::info($msg); return $connection->send($msg); } }
web.php
新增一条路由\BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter::webSocket('/my-websocket', \App\MyCustomWebSocketHandler::class);
客户端监听
ws://127.0.0.1:6001/my-websocket
beyondcode/laravel-websockets 自带了一个 Debug Dashboard
备注
1.在监听私有频道时,如果auth guard 为其它时,channels.php
Broadcast::channel('get-device-info.{id}', function ($user, $id) {
// 验证当前登录的用户id是否等于他监听的私有频道的id
return (int) $user->id === (int) $id;
}, ['guards' => ['wechat_user']]);
本作品采用《CC 协议》,转载必须注明作者和本文链接
laravel9里面可以试试看soketi
不过soketi禁止大陆IP访问,需要特殊处理才能打开。
方便做集群部署吗
好的,我等会试一下
这样子行不行,我项目index.php不在public目录,在根目录里,所以用不了@vite blade指令
刚好问一下 api/broadcasting/auth 授权返回如何不让返回user所有信息,只返回指定信息
大佬,vite那块不是很懂,我用的soketi,在dnmp里面,php容器里expose了5173端口,然后nginx容器里也映射了,所有环境都弄好了,然后npm run dev没效果,直接就找不到vite的client.js啥的,必须npm run build 然后写js代码的时候我那script里必须这样写,script要加个 type="module"才生效
我都通了,但是不知道前端为什么没有listen到 不能够打印出来
就是没有报错哦,可以加个联系方式 跟您请教一下吗,这个问题已经困扰我2天了
大佬,想请教一下,我在使用laravel9+laravel-websockets时,本地能够很好的连接,但是放到服务器上使用https,就无法连接上,请问有什么解决的办法吗?
个人建议独立使用 workman 做 websocket 服务器,用着清爽,laravel提供的各种插件,配置难度大,且通讯断断续续。使用 GatewayWorker 能快速开发相关功能,前端通过调用 lLaravel 或者 tp 等 php 常规框架的接口,接口在调用 websocket 服务器,就能完美解决 websocket 通讯问题,实现了聊天室、客服,包括小程序中的各种实时交互与应用相关的功能。可以看 demo(https://element.wmhello.cn)