• PHP 代码 清理 redis 消息问题


    关注 码龄 粉丝数 原力等级 -- 被采纳 被点赞 采纳率 aabbabababaa 2024-05-07 13:32 采纳率: 100% 浏览 4 首页/ 编程语言 / 已结题 PHP 代码 清理 redis 消息问题 phpredis public static function onClose($client_id, $message) { RedisHelper::clearallmsg($_SESSION['sn']); } 定义一个窗口关闭函数,引用了清理 redis 消息 private static function getUser($redis, $sn, $data, $add = false) { if ( $add ) { $data = [ //'id' => $data['id'], 'name' => $data['name'], 'passwd' => $data['passwd'], 'img' => $data['img'], ]; return $redis->hset($sn .':user', $data['name'], json_encode($data, JSON_UNESCAPED_UNICODE)); } $data = $redis->hget($sn .':user', $data['name']); return json_decode($data, true); } 找了 AI 回复 private static function clearAllMsg($redis, $sn) { // 获取所有用户的名称列表 $userNames = $redis->hKeys($sn . ':user'); // 遍历所有用户 foreach ($userNames as $userName) { // 构造该用户的“from”好友关系哈希表的键 $fromFriendHashKey = $sn . ':friend:' . $userName; // 获取该用户的所有“from”好友 $fromFriends = $redis->hGetAll($fromFriendHashKey); // 遍历“from”好友,并清空未读消息计数 foreach ($fromFriends as $toUserName => $friendData) { $friend = json_decode($friendData, true); if (isset($friend['unread'])) { $friend['unread'] = 0; $redis->hSet($fromFriendHashKey, $toUserName, json_encode($friend, JSON_UNESCAPED_UNICODE)); } } // 构造该用户的“to”好友关系哈希表的键(理论上与“from”是相同的,但为了完整性还是列出) $toFriendHashKey = $sn . ':friend:' . $userName; // 注意:这里和 from 是一样的,因为好友关系是双向的 // 获取该用户作为“to”的所有好友关系(通常这些与“from”是镜像的,但为了安全起见还是检查一遍) $toFriends = $redis->hGetAll($toFriendHashKey); // 遍历“to”好友,并清空未读消息计数(理论上这一步是多余的,因为数据是共享的) foreach ($toFriends as $fromUserName => $friendData) { $friend = json_decode($friendData, true); if (isset($friend['unread'])) { $friend['unread'] = 0; $redis->hSet($toFriendHashKey, $fromUserName, json_encode($friend, JSON_UNESCAPED_UNICODE)); } } } // 返回操作成功的信息 return true; } 但试了下,函数 clearAllMsg 不起作的。 在前端加了代码,也打印不出来数据 for (var key in fromFriendHashKey) { console.log("Key: " + key + ", Value: " + fromFriendHashKey[key]); } // 遍历并打印出$toFriendHashKey 的所有值 for (var key in toFriendHashKey) { console.log("Key: " + key + ", Value: " + toFriendHashKey[key]); } 然后在服务器连接 redis-cli -h 127.0.0.1 -p 6379keys *也没有数据。但是前端是可以登陆看到消息记录的 展开全部 收起 写回答 好问题 0 提建议 追加酬金 关注问题 微信扫一扫 点击复制链接 分享 邀请回答 编辑 收藏 删除 收藏 举报 追加酬金 (90%的用户在追加酬金后获得了解决方案) 当前问题酬金 ¥ 0 (可追加 ¥500) ¥ 15¥ 20¥ 50¥ 100¥ 200 支付方式 扫码支付 二维码出错 点击刷新 支付金额 15 元 提供问题酬金的用户不参与问题酬金结算和分配 支付即为同意 《付费问题酬金结算规则》 结题 再想想 删除 再等等

    4条回答 默认 最新

    • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-07 13:32
      关注

      引自免费微信小程序:皆我百晓生

      看起来您想要实现的是当用户关闭窗口时清除其在 Redis 中的相关会话数据,包括从其他用户那里接收到的消息的未读计数。首先,让我们分析一下现有的代码和可能的问题。

      1. clearAllMsg 函数中的问题:

        • 在遍历 $fromFriendHashKey$toFriendHashKey 时,使用了错误的数据结构。在 JavaScript 中,您应该使用 Object.keys() 方法来获取对象的键,而不是直接使用 for...in 循环。
        • 您没有调用 clearAllMsg 函数,所以它不会执行。确保在适当的地方调用这个方法,比如在 onClose 函数里。
      2. 前端代码问题:

        • 使用 for...in 循环遍历 JavaScript 对象时,可能会包含非可枚举属性,因此推荐使用 Object.keys()Object.entries() 来遍历对象的键值对。
      3. Redis 数据存储问题:

        • 如果您确认 Redis 中确实有数据,但是在使用 keys * 命令时找不到数据,可能是因为键前缀不正确,或者数据在其他数据库实例中。

      根据上述分析,我将提供修改后的代码片段:

      首先,在 clearAllMsg 函数中使用正确的键访问方式:

      private static function clearAllMsg($redis, $sn) {
          $userNames = $redis->hKeys($sn . ':user');
          
          foreach ($userNames as $userName) {
              $fromFriendHashKey = $sn . ':friend:' . $userName;
              $toFriendHashKey = $sn . ':friend:' . $userName;
      
              $fromFriends = $redis->hGetAll($fromFriendHashKey);
              $toFriends = $redis->hGetAll($toFriendHashKey);
      
              foreach (array_keys($fromFriends) as $toUserName) {
                  $friend = json_decode($fromFriends[$toUserName], true);
                  if (isset($friend['unread'])) {
                      $friend['unread'] = 0;
                      $redis->hSet($fromFriendHashKey, $toUserName, json_encode($friend, JSON_UNESCAPED_UNICODE));
                  }
              }
      
              foreach (array_keys($toFriends) as $fromUserName) {
                  $friend = json_decode($toFriends[$fromUserName], true);
                  if (isset($friend['unread'])) {
                      $friend['unread'] = 0;
                      $redis->hSet($toFriendHashKey, $fromUserName, json_encode($friend, JSON_UNESCAPED_UNICODE));
                  }
              }
          }
      
          return true;
      }
      

      接下来,在 onClose 函数中调用 clearAllMsg

      public static function onClose($client_id, $message) {
          RedisHelper::clearAllMsg(Redis::connection(), $_SESSION['sn']);
      }
      

      对于前端部分,由于您没有提供具体的前端框架或库,我将以纯 JavaScript 为例:

      function clearUnreadMessages(fromFriendHashKey, toFriendHashKey) {
          for (const key of Object.keys(fromFriendHashKey)) {
              console.log("Key: " + key + ", Value: " + fromFriendHashKey[key]);
          }
      
          for (const key of Object.keys(toFriendHashKey)) {
              console.log("Key: " + key + ", Value: " + toFriendHashKey[key]);
          }
      }
      
      // 在适当的位置调用此函数,例如用户关闭页面事件处理程序中
      window.addEventListener('beforeunload', () => {
          const fromFriendHashKey = ...; // 获取前端保存的 fromFriendHashKey 数据
          const toFriendHashKey = ...; // 获取前端保存的 toFriendHashKey 数据
          clearUnreadMessages(fromFriendHashKey, toFriendHashKey);
      });
      

      关于 Redis 数据的查找,确保您在正确的数据库实例中查询,并且键前缀匹配正确。您可以尝试在 Redis 客户端中指定数据库编号:

      redis-cli -h 127.0.0.1 -p 6379 -n  keys *
      

      其中 应替换为您的 Redis 数据库编号。

      如果您仍然遇到问题,请提供更多关于前端如何保存和使用 Redis 键以及用户会话信息的细节,以便我能提供更精确的帮助。

      展开全部

      本回答被题主选为最佳回答 , 对您是否有帮助呢?
      评论 编辑记录
      aabbabababaa 2024-05-07 16:16

      redis-cli -h 127.0.0.1 -p 6379 -n 原来是在分库1,看到数据了

      但是提示有报错

      public static function onClose($client_id, $message) {
          RedisHelper::clearAllMsg(Redis::connection(), $_SESSION['sn']);
      }
      

      pid:28676 ArgumentCountError: Too few arguments to function Events::onClose(), 1 passed and exactly 2 expected in/Applications/chat/Events.php:218
      Stack trace:
      #0 [internal function]: Events::onClose()

      回复
    查看更多回答(3条)
    编辑
    预览

    报告相同问题?

  • 相关阅读:
    ESP8266-Arduino编程实例-开发环境搭建(基于PlatformIO)
    vs2022 快捷键设置
    X METAVERSE PRO Launches Cloud Mining, Creating a “New Era of Mining Trend”
    软件测试金九银十即将到来,求职套路多你有多大把握拿offer
    最新版GNS3安装详解,小白也可以独立完成哦!!
    设计模式深度解析:适配器模式与桥接模式-灵活应对变化的两种设计策略大比拼
    CentOS 7下JumpServer安装及配置(超详细版)
    输入输出系统
    Prometheus(普罗米修斯)监控架构简介
    常用的Linux命令
  • 原文地址:https://ask.csdn.net/questions/8099784