zoukankan      html  css  js  c++  java
  • php + redis 实现关注功能

    产品价值

    1: 关注功能
    2: 功能分析之“关注”功能
    3: 平平无奇的「关注」功能,背后有4点重大价值

    应用场景

    在做PC或者APP端时,掺杂点社交概念就有关注和粉丝功能;
    数据量小的话数据库还能支持,如果数据量很庞大还是用缓存比较好。

    具体实现

    1 控制层实现

    <?php
    
    namespace AppControllerTest;
    
    use AppControllerAbstractController;
    use AppServicePtgTestFollowService;
    use HyperfDiAnnotationInject;
    use HyperfHttpServerAnnotationController;
    use HyperfHttpServerAnnotationMiddleware;
    use HyperfHttpServerAnnotationRequestMapping;
    
    /**
     * 测试 - 关注
     * Class TestFollowController
     * @package AppController
     * @Controller(prefix="test")
     */
    class TestFollowController extends AbstractController
    {
        /**
         * 服务层 - 关注
         * @Inject()
         * @var TestFollowService
         */
        protected $testFollowService;
    
        /**
         * 关注/取消关注
         * @param Request $request
         * @return mixed
         */
        public function follow(Request $request)
        {
            $type = $request->input('type', 'follow');         // 1-关注-follow 2-取消关注-remove
            $userId = $request->input('user_id', 0);    // 我的用户ID
            $otherId = $request->input('other_id', 0);  // 我关注的用户ID
            if ($userId == $otherId) {
                return $this->response->apiResponse();
            }
            $this->testFollowService->follow($type, $userId, $otherId);
            return $this->response->apiResponse();
        }
    
        /**
         * 我的关注/粉丝
         * @param Request $request
         * @return mixed
         */
        public function myFollowAndFans(Request $request)
        {
            $type = $request->input('type', 'follow');  // 1-关注-follow 2-粉丝-fans
            $userId = $request->input('user_id', 0);    // 我的用户ID
            $page = $request->input('page', 1);         // 页码
            $limit = $request->input('limit', 10);      // 每页显示条数
            $res = $this->testFollowService->myFollowAndFans($userId, $type, $page, $limit);
            return $this->response->apiResponse($res);
        }
    }
    ?>
    

    2 服务层实现

    <?php
    
    namespace AppServicePtg;
    
    use AppRepositoryRedisTestFollowRedis;
    use AppServiceAbstractService;
    use HyperfDiAnnotationInject;
    
    class TestFollowService extends AbstractService
    {
        /**
         * 仓储层 - 关注
         * @Inject()
         * @var TestFollowRedis
         */
        protected $testFollowRedis;
    
        /**
         * 关注/取消关注
         * @param string $type
         * @param int $userId
         * @param int $otherId
         * @return mixed
         */
        public function follow($type = 'follow', int $userId, int $otherId)
        {
            // 关注
            if ($type === 'follow') {
                // 先处理 mysql
                // TODO mysql 操作
                // 然后处理 redis
                $this->testFollowRedis->zAddFollow($userId, $otherId);
                $this->testFollowRedis->zAddFans($otherId, $userId);
            }
            // 取消关注
            if ($type === 'remove') {
                // 先处理 mysql
                // TODO mysql 操作
                // 然后处理 redis
                $this->testFollowRedis->zRemFollow($userId, $otherId);
                $this->testFollowRedis->zRemFans($otherId, $userId);
            }
        }
    
        /**
         * 我的关注/粉丝
         * @param int $userId 当前登录用户的ID
         * @param string $type 要获取的数据
         * @param int $page 页码
         * @param int $limit 限制条数
         * @return array
         */
        public function myFollowAndFans(int $userId, $type = 'follow', $page = 1, $limit = 10)
        {
            $start = $limit * ($page - 1);
            $end = $start + $limit - 1;
            $res = [];
            if ($type === 'follow') {
                $res = $this->testFollowRedis->zRangeFollow($userId, $start, $end);
            }
            if ($type === 'fans') {
                $res = $this->testFollowRedis->zRangeFans($userId, $start, $end);
            }
            return $res;
        }
    }
    ?>
    

    仓储层实现

    <?php
    
    namespace AppRepositoryRedis;
    
    class TestFollowRedis extends AbstractRedis
    {
        /**
         * 关注key
         * @var string
         */
        private $followKey = '%u:follow';
    
        /**
         * 粉丝key
         * @var string
         */
        private $fansKey = '%u:fans';
    
        /**
         * 前缀
         */
        public function initPrefix()
        {
            return 'follow:';
        }
    
        /**
         * 增加关注
         * @param $userId
         * @param $otherId
         */
        public function zAddFollow($userId, $otherId)
        {
            $this->redis->zAdd(sprintf($this->prefix . $this->followKey, $userId), time(), $otherId);
        }
    
        /**
         * 取消关注
         * @param $userId
         * @param $otherId
         */
        public function zRemFollow($userId, $otherId)
        {
            $this->redis->zRem(sprintf($this->prefix . $this->followKey, $userId), $otherId);
        }
    
        /**
         * 我的关注 | 正序
         * @param int $userId
         * @param int $start
         * @param int $end
         * @return array
         */
        public function zRangeFollow(int $userId, int $start = 0, int $end = 9)
        {
            return $this->redis->zRange(sprintf($this->prefix . $this->followKey, $userId), $start, $end);
        }
    
        /**
         * 我的关注 | 倒序
         * @param int $userId
         * @param int $start
         * @param int $end
         * @return array
         */
        public function zRevRangeFollow(int $userId, int $start = 0, int $end = 9)
        {
            return $this->redis->zRevRange(sprintf($this->prefix . $this->followKey, $userId), $start, $end);
        }
    
        /**
         * 增加粉丝
         * @param $userId
         * @param $otherId
         */
        public function zAddFans($userId, $otherId)
        {
            $this->redis->zAdd(sprintf($this->prefix . $this->fansKey, $userId), time(), $otherId);
        }
    
        /**
         * 移除粉丝
         * @param $userId
         * @param $otherId
         */
        public function zRemFans($userId, $otherId)
        {
            $this->redis->zRem(sprintf($this->prefix . $this->fansKey, $userId), $otherId);
        }
    
        /**
         * 我的粉丝 | 正序
         * @param int $userId
         * @param int $start
         * @param int $end
         * @return array
         */
        public function zRangeFans(int $userId, int $start = 0, int $end = 9)
        {
            return $this->redis->zRange(sprintf($this->prefix . $this->fansKey, $userId), $start, $end);
        }
    
        /**
         * 我的粉丝 | 倒序
         * @param int $userId
         * @param int $start
         * @param int $end
         * @return array
         */
        public function zRevRangeFans(int $userId, int $start = 0, int $end = 9)
        {
            return $this->redis->zRevRange(sprintf($this->prefix . $this->fansKey, $userId), $start, $end);
        }
    }
    
  • 相关阅读:
    [算法] 堆栈
    [刷题] PTA 02-线性结构3 Reversing Linked List
    java IO流 (八) RandomAccessFile的使用
    java IO流 (七) 对象流的使用
    java IO流 (六) 其它的流的使用
    java IO流 (五) 转换流的使用 以及编码集
    java IO流 (四) 缓冲流的使用
    java IO流 (三) 节点流(或文件流)
    java IO流 (二) IO流概述
    java IO流 (一) File类的使用
  • 原文地址:https://www.cnblogs.com/laowenBlog/p/14192070.html
Copyright © 2011-2022 走看看