aabbabababaa 2024-05-07 13:32 采纳率: 100%
浏览 4
已结题

PHP 代码 清理 redis 消息问题

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 6379
keys *
也没有数据。但是前端是可以登陆看到消息记录的

  • 写回答

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 <database_number> keys *
    

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

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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 5月30日
  • 已采纳回答 5月22日
  • 创建了问题 5月7日

悬赏问题

  • ¥15 网站设计与开发职业技能大赛试题
  • ¥20 在使用CESM2.2.0模型进行case.submit过程中出现如下错误(关键词-Map)
  • ¥15 有办法改变通过wifi进入的网站的设置吗
  • ¥15 所以到底怎么算!算到凌晨五点都算不出来!
  • ¥15 label_studio
  • ¥15 请教如何phython发邮件
  • ¥15 linux系统安装问题
  • ¥15 路径规划如何采用矢量法让他们尽量在一个方向
  • ¥15 crypto 一道rsa解密题
  • ¥15 survIDINRI已将生存时间转为数值变量,仍错误 Time variable is not numeric。