WorkerMan实现即时通讯(Redis缓存用户信息和聊天记录)

使用redis缓存用户数据和聊天记录 Chat.php

<?php
/**
 * @author <fl140125@gmail.com>
 * Class Chat
 */
class Chat
{
    /**
     * @var Redis $redisClient
     */
    protected $redisClient;
    /**
     * @var string $hashKey
     */
    protected $hashKey = 'unread_';
    /**
     * Chat constructor.
     */
    public function __construct()
    {
        $this->redisClient = new Redis();
        $this->redisClient -> connect('127.0.0.1', 6379);
    }
    /**
     * TODO:缓存用户聊天记录
     * @param $from
     * @param $to
     * @param $room_id
     * @param $message
     * @return bool|int
     */
    public function setChatMsgLists($from, $to, $room_id, $message)
    {
        $value = str_replace('\\', '', json_encode($message, JSON_UNESCAPED_UNICODE));
        $keyName = $to == 'all' ? 'receive_all_'.$room_id : "receive_{$from}_{$to}";
        return $this ->redisClient-> lPush($keyName, $value);
    }
    /**
     * TODO:获取聊天记录
     * @param $from
     * @param $to
     * @param $room_id
     * @param int $page
     * @param int $limit
     * @return array
     */
    public function getChatMsgLists($from, $to, $room_id, $page = 1, $limit = 19)
    {
        $message = array();
        $time = array();
        $offset = $limit * ($page - 1) ;
        //群聊消息
        if (!empty($room_id)) {
            $recName = 'receive_all_'.$room_id;
            $num = $this->getMsgLen($recName);
            $recList = $offset + $limit >= $num ? $this ->redisClient-> lRange($recName, $offset, $num) :
                $this->redisClient->lRange($recName, $offset, $offset+$limit);
            foreach ($recList as $item) {
                array_push($message, json_decode($item, true));
                $time[] = json_decode($item, true)['time'];
            }
            array_multisort($message, $time, SORT_ASC);
            return array('list' => $message, 'total' => $num);
        }
        //接受的消息
        $recName =  "receive_{$from}_{$to}";
        $recNum = $this->getMsgLen($recName);
        $recList = $offset + $limit >= $recNum ? $this ->redisClient-> lRange($recName, $offset, $recNum) :
            $this->redisClient->lRange($recName, $offset, $offset+$limit);
        foreach ($recList as $item) {
            array_push($message, json_decode($item, true));
            $time[] = json_decode($item, true)['time'];
        }
        //发送的消息
        $sendName = "receive_{$to}_{$from}";
        $sendNum = $this->getMsgLen($sendName);
        $sendLists = $offset + $limit >= $sendNum ? $this ->redisClient-> lRange($sendName, $offset, $sendNum) :
            $this->redisClient->lRange($sendName, $offset, $offset+$limit);
        foreach ($sendLists as $item) {
            array_push($message, json_decode($item, true));
            $time[] = json_decode($item, true)['time'];
        }
        array_multisort($message, $time, SORT_ASC);
        return array('list' => $message, 'total' => $recNum + $sendNum);
    }
    /**
     * todo:消息撤回:删除redis缓存数据并告知用户/消息删除:直接删除消息
     * @param $message
     */
    public function recallMessage($message)
    {
        $receiveKey = empty($message['room_id']) ? "receive_{$message['from_client_id']}_{$message['to_client_id']}" :
            "receive_all_{$message['room_id']}";
        $num = $this->getMsgLen($receiveKey);
        $recList = $this ->redisClient-> lRange($receiveKey, 0, (int)($num));
        $newRecList = array();
        foreach ($recList as $index => $item) {
            if (!$this->compareJson(json_encode($message, JSON_UNESCAPED_UNICODE), $item)) {
                array_push($newRecList, json_decode($item, true));
            }
        }
        //删除redisKey重新赋值
        $this->redisClient->del($receiveKey);
        foreach ($newRecList as $row) {
            $this->setChatMsgLists($row['from_client_id'], $row['to_client_id'], $row['room_id'], $row);
        }
    }

    /**
     * todo:json字符串比较
     * @param $jsonA
     * @param $jsonB
     * @param $field
     * @return bool
     */
    protected function compareJson($jsonA, $jsonB, $field = ['type'])
    {
        $jsonA = json_decode($jsonA, true);
        $jsonB = json_decode($jsonB, true);
        if (count($jsonB)!== count($jsonA)) {
            return false;
        }
        $total = count($jsonA);
        $num = count($field);
        foreach ($jsonA as $i => $a) {
            if (!in_array($i, $field) && $jsonA[$i] == $jsonB[$i]) {
                $num++;
            }
        }
        return $num === $total;
    }
    /**
     * TODO:获取聊天记录长度
     * @param $key
     * @return int
     */
    protected function getMsgLen($key)
    {
        return $this->redisClient->lLen($key);
    }
    /**
     * TODO:获取用户未读消息记录数(所有)
     * @param $to
     * @return array
     */
    public function getUnreadMsgAllCount($to)
    {
        return $this ->redisClient-> hGetAll($this->hashKey.$to);
    }

    /**
     * TODO:获取用户未读消息记录数(单个)
     * @param $to
     * @param $from
     * @return string
     */
    public function getUnreadMsgCount($to, $from)
    {
        return $this ->redisClient-> hGet($this->hashKey.$to, $from);
    }
    /**
     * TODO:包括所有未读消息内容的数组
     * @param $from
     * @param $to
     * @return array
     */
    public function getUnreadMsg($from, $to)
    {
        $countArr = $this -> getUnreadMsgAllCount($to);
        $count = $countArr[$from];
        $keyName = "receive_{$from}_{$to}";
        return $this ->redisClient -> lRange($keyName, 0, (int)($count));
    }
    /**
     * TODO:添加用户未读消息记录数
     * @param $from
     * @param $to
     * @return int
     */
    public function setUnreadMsgLists($from, $to)
    {
        return $this->redisClient->hIncrBy($this->hashKey.$to, $from, 1);
    }
    /**
     * TODO:删除未读消息
     * @param $from
     * @param $to
     * @return bool|int
     */
    public function delUnreadMsg($from, $to)
    {
        return $this->redisClient->hDel($this->hashKey.$from, $to);
    }
    /**
     * TODO:判断是否存在
     * @param $key
     * @param $value
     * @return bool
     */
    public function sIsMember($key, $value)
    {
        return $this->redisClient->sIsMember($key, $value);
    }
    /**
     * TODO:获取集合
     * @param $key
     * @return array
     */
    public function sMembers($key)
    {
        return $this->redisClient->SMEMBERS($key);
    }

    /**
     * TODO:添加数据到集合
     * @param string $string
     * @param $uid
     * @return bool|int
     */
    public function sAdd(string $string, $uid)
    {
        return $this->redisClient->sAdd($string, $uid);
    }
    /**
     * TODO:数据存储 (Redis 字符串(String))
     * @param $key
     * @param $value
     * @param int $timeout
     * @return bool
     */
    public function setValue($key, $value, $timeout = 0)
    {
        return $this->redisClient->set($key, $value, $timeout);
    }
    /**
     * TODO:数据获取(Redis 字符串(String))
     * @param $key
     * @return bool|string
     */
    public function getValue($key)
    {
        return $this->redisClient->get($key);
    }

    /**
     * todo:删除集合数据
     * @param string $string
     * @param $uid
     * @return int
     */
    public function sRem(string $string, $uid)
    {
        return $this->redisClient->sRem($string, $uid);
    }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值