【问题标题】:How to send message back from client to the server via WebSocket in Laravel with Laravel WebSockets?如何使用 Laravel WebSockets 通过 Laravel 中的 WebSocket 将消息从客户端发送回服务器?
【发布时间】:2020-05-02 07:47:11
【问题描述】:

WebSocket 允许双向通信:服务器可以向浏览器发送消息,而浏览器(客户端)可以通过同一连接进行响应。

我正在使用 Laravel 6 实现聊天应用程序:

我已经知道服务器触发事件​​并且客户端监听这些事件如下。

  1. 安装 Laravel WebSockets 包。

composer require beyondcode/laravel-websockets

  1. 配置config/broadcasting.php。
        'pusher' => [
            'driver' => 'pusher',
            'key' => xxx,
            'secret' => xxx,
            'app_id' => xxx,
            'options' => [
                'cluster' => xxx,
                'encrypted' => true,
                'useTLS' => true, 
                'host' => '127.0.0.1',
                'port' => 6001,
                'scheme' => 'https',
            ],
        ],
    ]
  1. 配置config/websockets.php
'apps' => [
        [
            'id' => xxx,
            'name' => xxx,
            'key' => xxx,
            'secret' => xxx,
            'enable_client_messages' => true,
            'enable_statistics' => true,
        ],
    ],
  1. 安装Pusher服务器。

composer require pusher/pusher-php-server "~3.0"

  1. 将广播驱动程序设置为在.env 文件中使用pusher。

BROADCAST_DRIVER=pusher

  1. 在我的客户端使用laravel-echo 和pusher-js。
import Echo from "laravel-echo"

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key',
    wsHost: window.location.hostname,
    wsPort: 6001,
    disableStats: true,
});
  1. 启动 WebSockets 服务器。

php artisan websockets:serve

  1. 在服务器端,使用实现ShouldBroadcastNow 类的事件类触发事件。

event(new MyEventClass((object)$message));

一切正常。在第 8 步中,我从服务器端触发事件。

请注意,我没有使用官方的 Pusher 服务器,我只是使用 Pusher API 实现和 pusher-js,但将 Laravel Echo JavaScript package 指向本地 Laravel WebSockets server,在步骤 6 中配置。

请不要将Laravel Echo JavaScript package 与laravel-echo-server 或Socket.IO Server 混淆。我没有使用Socket.IO Server。

现在我不想像第 8 步那样在服务器端触发事件,而是想从客户端触发事件,因为 WebSocket 允许双向通信。我如何在Laravel 和Laravel Echo JavaScript Package、Laravel WebSockets PHP package 中做到这一点?

【问题讨论】:

标签: javascript php laravel websocket laravel-websockets


【解决方案1】:

请参阅此文档:https://pusher.com/docs/channels/using_channels/events#triggering-client-events

根据 pusher 文档,使用 this 初始化您的前端

 this.echo = new Pusher('mykey', {
    wsHost: 'localhost',
    wsPort: 6001,
    forceTLS: false,
    disableStats: true,
    enabledTransports: ['ws', 'wss']
  });

用它来触发你的事件

var channel = this.echo.subscribe("private-channel");
channel.bind("pusher:subscription_succeeded", () => {
var triggered = channel.trigger("client-someEventName", {
   your: "data",
 });
});

【讨论】:

    【解决方案2】:

    初始化 Echo 后,您需要在前端的某个频道上收听。我将展示一些 Vue 代码,但要进行相应的修改:

    Vue 文件

    export default {
        methods: {
            sendCommand(command) {
                axios.post('/api/command', { 'command': command })
                .then((res) => {
                    //
                })
            }
        },
        mounted() {
            Echo.channel('xxx')
            .listen('.weight-change', (e) => {
                this.weight = e.weight
            })
        }
    }
    

    在这里,您可以看到所有传入的消息都在代码的侦听部分捕获,并且通过后端的 api 路由将新消息发送到 Echo 通道来完成发送新消息。

    如果您需要任何说明,请告诉我。

    【讨论】:

    • 这与我所做的第 8 步相同,使用axios.post('/api/command'),您可以对服务器进行 API 调用以触发事件。因此,事件在服务器端被触发。我正在寻找在客户端触发事件的解决方案。当您在调用 axios.post() 的 VueJs 组件中的客户端调用 sendCommand(command) 方法时,并不意味着您会在客户端触发事件。
    【解决方案3】:

    适用于所有可能面临此问题的人。

    你不需要回显,应该直接从 Pusher 实例化

    const my_pusher = new Pusher("APP_KEY", {
            cluster: 'mt1',
            wsHost: window.location.hostname,
            wsPort: 6001,
            forceTLS: false,
            disableStats: true,
        });
    

    并向服务器发送消息:

    my_pusher.send_event('EVENT_NAME',{'ANYTHING':'YOU_WANT'})
    

    【讨论】:

    • 你不会用这个来攻击服务器,它是唯一的客户端。因此,您无法对数据进行任何验证或任何操作。
    • @MichaelAndersen 通过这段代码,客户端可以向服务器发送任何事件。任何验证都可以在服务器端提供
    【解决方案4】:

    我可能不正确,但我不相信您可以使用他们的 pusher-js 包推送到 Pusher。这就是 pusher-php-server composer 包的用途。

    这可能有一个节点包,但你为什么要重新发明轮子?只需使用 axios 或 Vuex 操作发布到您的一条路线以触发您的事件,然后让 Echo 获取响应。

    您甚至不需要创建控制器,只需使用路由关闭并触发您的事件。 Axios 或 Vuex 都将返回一个 Promise,因此您可以在组件或 Vuex 操作中管理等待响应。

    如果您尝试使用 RabbitMQ 或 Rachet 之类的方式实现不同类型的广播驱动程序,我可以理解,但它被设计为某种循环循环,从 js 访问您的端点,从 PHP 触发事件,让 Pusher/或 websockets 做这件事,用 js 接收你的广播。

    【讨论】:

      猜你喜欢
      • 2018-11-10
      • 2018-07-05
      • 2022-07-15
      • 2017-09-15
      • 2020-09-06
      • 1970-01-01
      • 2018-10-25
      • 2020-03-10
      • 1970-01-01
      相关资源
      最近更新 更多