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处理程序

  1. 创建 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);
    }
    }
  2. web.php新增一条路由

    \BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter::webSocket('/my-websocket', \App\MyCustomWebSocketHandler::class);
  3. 客户端监听

    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 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 33

laravel9里面可以试试看soketi

不过soketi禁止大陆IP访问,需要特殊处理才能打开。

1年前 评论
会尿尿的大鲨鱼 (楼主) 1年前
91it (作者) 1年前

方便做集群部署吗

1年前 评论
会尿尿的大鲨鱼 (楼主) 1年前

好的,我等会试一下

1年前 评论
会尿尿的大鲨鱼 (楼主) 1年前

这样子行不行,我项目index.php不在public目录,在根目录里,所以用不了@vite blade指令

Laravel

1年前 评论

刚好问一下 api/broadcasting/auth 授权返回如何不让返回user所有信息,只返回指定信息

1年前 评论
会尿尿的大鲨鱼 (楼主) 1年前

大佬,vite那块不是很懂,我用的soketi,在dnmp里面,php容器里expose了5173端口,然后nginx容器里也映射了,所有环境都弄好了,然后npm run dev没效果,直接就找不到vite的client.js啥的,必须npm run build 然后写js代码的时候我那script里必须这样写,script要加个 type="module"才生效

@vite('resources/js/app.js')
<script type="module">
    Echo.channel('test_channel')
        .listen('TestEvent', (e) => {
            console.log(e)
        })
</script>
1年前 评论

我都通了,但是不知道前端为什么没有listen到 不能够打印出来

1年前 评论
会尿尿的大鲨鱼 (楼主) 1年前

就是没有报错哦,可以加个联系方式 跟您请教一下吗,这个问题已经困扰我2天了

1年前 评论
臭鼬 1年前
会尿尿的大鲨鱼 (楼主) 1年前
Edison_SR (作者) 1年前
Edison_SR (作者) 1年前
Edison_SR (作者) 1年前
臭鼬 1年前
臭鼬 1年前
Edison_SR (作者) 1年前
臭鼬 1年前
Edison_SR (作者) 1年前
臭鼬 1年前

大佬,想请教一下,我在使用laravel9+laravel-websockets时,本地能够很好的连接,但是放到服务器上使用https,就无法连接上,请问有什么解决的办法吗?

1年前 评论
会尿尿的大鲨鱼 (楼主) 1年前
Yolver (作者) 1年前
会尿尿的大鲨鱼 (楼主) 1年前
Yolver (作者) 1年前
臭鼬 1年前

个人建议独立使用 workman 做 websocket 服务器,用着清爽,laravel提供的各种插件,配置难度大,且通讯断断续续。使用 GatewayWorker 能快速开发相关功能,前端通过调用 lLaravel 或者 tp 等 php 常规框架的接口,接口在调用 websocket 服务器,就能完美解决 websocket 通讯问题,实现了聊天室、客服,包括小程序中的各种实时交互与应用相关的功能。可以看 demo(https://element.wmhello.cn)

8个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!