Php 拉威尔+;棘轮:将通知推送到特定客户端

Php 拉威尔+;棘轮:将通知推送到特定客户端,php,laravel,notifications,pusher,ratchet,Php,Laravel,Notifications,Pusher,Ratchet,我是WebSocket新手,我想在我的Laravel应用程序中实现这样的服务。 我已经读了好几篇关于这个主题的文章/页面,但没有一篇解释我需要做什么。所有这些都展示了如何创建一个“Echo”websocket服务器,其中服务器只响应从客户端接收到的消息,这不是我的情况 作为起点,我使用了以下提供的代码: 其中websocket服务器是从命令行或其他控制台运行的。服务器有自己的类来定义它,并导入WebSocketController类(MessageComponentInterface),该类包

我是WebSocket新手,我想在我的Laravel应用程序中实现这样的服务。 我已经读了好几篇关于这个主题的文章/页面,但没有一篇解释我需要做什么。所有这些都展示了如何创建一个“Echo”websocket服务器,其中服务器只响应从客户端接收到的消息,这不是我的情况

作为起点,我使用了以下提供的代码:

其中websocket服务器是从命令行或其他控制台运行的。服务器有自己的类来定义它,并导入WebSocketController类(MessageComponentInterface),该类包含经典的WebSocket服务器事件(onOpen、onMessage、onClose、onError)

所有这些都可以正常工作,但是,我如何“告诉”WebSocket服务器从另一个类(也属于另一个命名空间)向特定连接(客户机)发送消息呢?。这是通知或事件的情况,其中新的web内容必须发送到特定的客户端。没有来自客户端的订阅或发布

正如@Alias在他的帖子中所问的,我显然无法创建Websocket服务器或其事件管理类的新实例,那么向客户端发送内容或消息的最佳方法是什么

正如大家所看到的,通信只有一种方式:从WebSocket服务器到客户端,而不是相反。 我已经为此准备了一个通知类和一个侦听器类,但我仍然不知道如何通过handle()方法处理与客户端的通信:


好的,在学习和研究了很多之后,我可以把一个类似问题的答案发布在:

根据我在这篇文章的第二条评论中所写的内容,这就是我找到的解决方案

我使用composer为websocket服务器安装了cboden/Ratchet包。 当后端触发事件时,我需要向用户/用户组发送通知,或更新UI

我所做的是:

1)使用composer安装了AmHP/websocket客户端软件包

2)创建了一个单独的类,以便实例化可以连接到websocket服务器的对象,发送所需消息并断开连接:

namespace App;
use Amp\Websocket\Client;

class wsClient {

   public function __construct() {
      //
   }


   // Creates a temporary connection to the WebSocket Server
   // The parameter $to is the user name the server should reply to.
   public function connect($msg) {
      global $x;
      $x = $msg;
      \Amp\Loop::run(
         function() {
            global $x;
            $connection = yield Client\connect('ws://ssa:8090');
            yield $connection->send(json_encode($x));
            yield $connection->close();
            \Amp\Loop::stop();
         }
      );
   }
}
3)webSocket服务器处理程序类中的
onMessage()
事件如下所示:

   /**
    * @method onMessage
    * @param  ConnectionInterface $conn
    * @param  string              $msg
    */   
   public function onMessage(ConnectionInterface $from, $msg) {
      $data = json_decode($msg);
      // The following line is for debugging purposes only
      echo "   Incoming message: " . $msg . PHP_EOL;
      if (isset($data->username)) {
         // Register the name of the just connected user.
         if ($data->username != '') {
            $this->names[$from->resourceId] = $data->username;
         }
      }
      else {
         if (isset($data->to)) {
            // The "to" field contains the name of the users the message should be sent to.
            if (str_contains($data->to, ',')) {
               // It is a comma separated list of names.
               $arrayUsers = explode(",", $data->to);
               foreach($arrayUsers as $name) {
                  $key = array_search($name, $this->names);
                  if ($key !== false) {
                     $this->clients[$key]->send($data->message);
                  }
               }
            }
            else {
               // Find a single user name in the $names array to get the key.
               $key = array_search($data->to, $this->names);
               if ($key !== false) {
                  $this->clients[$key]->send($data->message);
               }
               else {
                  echo "   User: " . $data->to . " not found";
               }
            }
         } 
      }

      echo "  Connected users:\n";
      foreach($this->names as $key => $data) {
         echo "   " . $key . '->' . $data . PHP_EOL;
      }
   }
   public function onOpen(ConnectionInterface $conn) {
      // Store the new connection to send messages to later
      $this->clients[$conn->resourceId] = $conn;
      echo " \n";
      echo "  New connection ({$conn->resourceId}) " . date('Y/m/d h:i:sa') . "\n";
   }
如您所见,希望websocket服务器将消息发送到的用户在$msg参数中与消息本身($data->message)一起指定为字符串($data->to)。这两个东西都是JSON编码的,因此参数$msg可以被视为一个对象

4)在客户端(布局刀片文件中的javascript),当客户端连接时,我将用户名发送到websocket服务器:

var currentUser = "{{ Auth::user()->name }}";
socket = new WebSocket("ws://ssa:8090");

socket.onopen = function(e) {
   console.log(currentUser + " has connected to websocket server");
   socket.send(JSON.stringify({ username: currentUser }));
};

socket.onmessage = function(event) {
   console.log('Data received from server: ' + event.data);
};
因此,用户名及其连接号保存在websocket服务器中

5)处理程序类中的
onOpen()
方法如下所示:

   /**
    * @method onMessage
    * @param  ConnectionInterface $conn
    * @param  string              $msg
    */   
   public function onMessage(ConnectionInterface $from, $msg) {
      $data = json_decode($msg);
      // The following line is for debugging purposes only
      echo "   Incoming message: " . $msg . PHP_EOL;
      if (isset($data->username)) {
         // Register the name of the just connected user.
         if ($data->username != '') {
            $this->names[$from->resourceId] = $data->username;
         }
      }
      else {
         if (isset($data->to)) {
            // The "to" field contains the name of the users the message should be sent to.
            if (str_contains($data->to, ',')) {
               // It is a comma separated list of names.
               $arrayUsers = explode(",", $data->to);
               foreach($arrayUsers as $name) {
                  $key = array_search($name, $this->names);
                  if ($key !== false) {
                     $this->clients[$key]->send($data->message);
                  }
               }
            }
            else {
               // Find a single user name in the $names array to get the key.
               $key = array_search($data->to, $this->names);
               if ($key !== false) {
                  $this->clients[$key]->send($data->message);
               }
               else {
                  echo "   User: " . $data->to . " not found";
               }
            }
         } 
      }

      echo "  Connected users:\n";
      foreach($this->names as $key => $data) {
         echo "   " . $key . '->' . $data . PHP_EOL;
      }
   }
   public function onOpen(ConnectionInterface $conn) {
      // Store the new connection to send messages to later
      $this->clients[$conn->resourceId] = $conn;
      echo " \n";
      echo "  New connection ({$conn->resourceId}) " . date('Y/m/d h:i:sa') . "\n";
   }
每次客户端连接到websocket服务器时,其连接号或resourceId都存储在一个数组中。因此,用户名存储在一个数组($names)中,密钥存储在另一个数组($clients)中

6)最后,我可以在项目中的任何位置创建一个PHP websocket客户端(wsClient)实例,向任何用户发送任何数据:

在本例中,我使用通知事件侦听器的handle()方法


好的,这是为那些想知道如何从PHP websocket服务器(也称为echo服务器)向一个特定客户端或一组客户端发送消息的人准备的。

好的,我一直在玩RatchetPHP/Pawl,它可以作为PHP客户端工作,但它也会阻止我的javascript websocket客户端。一旦Pawl断开连接,javascript websocket客户端就会连接。这看起来像是Pawl创建的循环,阻止了js客户端。我需要用PHP向JS websocket客户端发送通知,而不阻止它们。通过安装Amhp/websocket客户端,我可以建立一个PHP客户端连接,向websocket服务器发送消息,并告诉它将回复发送到另一个连接。但是,如果用户浏览应用程序菜单/链接,则随后的HTML请求会断开javascript websocket客户端的连接。读一读关于它的文章,我需要将JSWebSocket保存在web worker中,以保持连接的活力。如果没有,将在下一页创建一个新连接,这将使维护变得更加困难,并生成更多的网络流量来更新连接表/列表。