美文网首页
Laravel 中操作 Redis

Laravel 中操作 Redis

作者: 发条夏 | 来源:发表于2018-12-26 10:18 被阅读0次

    需求:

    今天的开发需求是记录web和pc端的访问量。初步思路是在controller入口进行记录。使用redis中的Hash数据类型。key为日期,value为次数,正好Hash提供了累加(hincrby)操作,可以满足要求。目前的时间粒度是按照天数,后期扩展的时候可以将时间粒度进行细分。

    ""

    编码:

    在laravel中的那个地方进行次数的统计呢?有两个地方,一个是BaseController,还有一个中间件,所有的请求均经过这里。在统计的时候需要注意的是进行过滤一些请求,比如接口post请求,来自后台管理系统的请求等等。

    //基类controller构造函数
     public function __construct(Request $request) 
        {
            $requestParam = request()->route()->getAction(); //获取访问的url
            $domain = [env('WECHAT_SUB_ROUTE'), env('FRONTEND_SUB_ROUTE')];//参与次数统计的rul
            if (in_array($requestParam['domain'], $domain) && $request->isMethod('get')) {
                $hashKey = 'webVisits';
                Redis::hincrby($hashKey, date('Y-m-d'), 1);//存入redis的hash
            }
        }
    
    //getAction方法可以取到的值
    array:8 [▼
      "domain" => "www.laravelylw.com"
      "middleware" => array:5 [▶]
      "as" => "xiong.test"
      "uses" => "App\Http\Controllers\Home\Main\XiongTestController@index"
      "controller" => "App\Http\Controllers\Home\Main\XiongTestController@index"
      "namespace" => "App\Http\Controllers\Home\Main"
      "prefix" => null
      "where" => []
    ]
    
    redis中储存的值

    根据需求可以看到会按照月和周进行比较。所以初步思路是获取某个时间段的startTime和endTime,然后通过Redis::hgetall($key)获取到哈希表中所有的key-value,以数组的方式返回。


    redis通过hgetall获取的

    然后遍历数组,将每个值和startTime-endTime比较,是否在该范围,若在就进行累加,即可得到这个时间段的访问量总和。

        //本周访问量
        $memberVisiyNum_week =$this->getVisit(Time::week());
        //date是一个数组包含startTIme和endTIme,获取本周,上周,本月,上个月等时间工具在后面附上。
        //还使用到Carbon工具类,用法见https://9iphp.com/web/laravel/php-datetime-package-carbon.html
        private function getVisit($date){
            $key = 'webVisits';//hash的key
            $lists = Redis::hgetall($key);//返回整个hash表元素
            $visit = 0;
            $Carbon = new Carbon();
            $startTime = $Carbon->create(date('Y',$date[0]),date('m',$date[0]),date('d',$date[0]),0,0,0);//用于后面使用Carbon种的日期比较方法
            $endTime = $Carbon->create(date('Y',$date[1]),date('m',$date[1]),date('d',$date[1]),0,0,0);
            foreach ($lists as $k => $v){
                $vTime = $Carbon->create(date('Y',strtotime($k)),date('m',strtotime($k)),date('d',strtotime($k)),0,0,0);//可以兼容细化时间粒度后。
                if($vTime->gte($startTime) && $vTime->lte($endTime)){
                    $visit = $visit + Redis::hget($key,$k);
                }
            }
            return $visit;
        }
    

    至此编码结束。

    优化

    可以优化的地方有以下几个。
    1、时间粒度的优化,目前的业务是统计到天,没准哪天运营说我要看看每天那个时间段访问量最多。如果将时间粒度细化了,是否还能兼容现在的getVisit方法呢,是可以的。
    2、通过Redis::hgetall($key)取值的时候,我们其实每次不需要都取出来,根据业务需求,最多60天的数据就ok了,如果每次都取出来,foreach的时候很浪费时间。

    Time()工具类

    class Time
    {
        /**
         * 返回今日开始和结束的时间戳
         *
         * @return array
         */
        public static function today()
        {
            return [
                mktime(0, 0, 0, date('m'), date('d'), date('Y')),
                mktime(23, 59, 59, date('m'), date('d'), date('Y'))
            ];
        }
    
        /**
         * 返回昨日开始和结束的时间戳
         *
         * @return array
         */
        public static function yesterday()
        {
            $yesterday = date('d') - 1;
            return [
                mktime(0, 0, 0, date('m'), $yesterday, date('Y')),
                mktime(23, 59, 59, date('m'), $yesterday, date('Y'))
            ];
        }
    
        /**
         * 返回本周开始和结束的时间戳
         *
         * @return array
         */
        public static function week()
        {
            $timestamp = time();
            return [
                strtotime(date('Y-m-d', strtotime("this week Monday", $timestamp))),
                strtotime(date('Y-m-d', strtotime("this week Sunday", $timestamp))) + 24 * 3600 - 1
            ];
        }
    
        /**
         * 返回上周开始和结束的时间戳
         *
         * @return array
         */
        public static function lastWeek()
        {
            $timestamp = time();
            return [
                strtotime(date('Y-m-d', strtotime("last week Monday", $timestamp))),
                strtotime(date('Y-m-d', strtotime("last week Sunday", $timestamp))) + 24 * 3600 - 1
            ];
        }
    
        /**
         * 返回本月开始和结束的时间戳
         *
         * @return array
         */
        public static function month($everyDay = false)
        {
            return [
                mktime(0, 0, 0, date('m'), 1, date('Y')),
                mktime(23, 59, 59, date('m'), date('t'), date('Y'))
            ];
        }
    
        /**
         * 返回上个月开始和结束的时间戳
         *
         * @return array
         */
        public static function lastMonth()
        {
            $begin = mktime(0, 0, 0, date('m') - 1, 1, date('Y'));
            $end = mktime(23, 59, 59, date('m') - 1, date('t', $begin), date('Y'));
    
            return [$begin, $end];
        }
    
        /**
         * 返回今年开始和结束的时间戳
         *
         * @return array
         */
        public static function year()
        {
            return [
                mktime(0, 0, 0, 1, 1, date('Y')),
                mktime(23, 59, 59, 12, 31, date('Y'))
            ];
        }
    
        /**
         * 返回去年开始和结束的时间戳
         *
         * @return array
         */
        public static function lastYear()
        {
            $year = date('Y') - 1;
            return [
                mktime(0, 0, 0, 1, 1, $year),
                mktime(23, 59, 59, 12, 31, $year)
            ];
        }
    
        public static function dayOf()
        {
    
        }
    
        /**
         * 获取几天前零点到现在/昨日结束的时间戳
         *
         * @param int $day 天数
         * @param bool $now 返回现在或者昨天结束时间戳
         * @return array
         */
        public static function dayToNow($day = 1, $now = true)
        {
            $end = time();
            if (!$now) {
                list($foo, $end) = self::yesterday();
            }
    
            return [
                mktime(0, 0, 0, date('m'), date('d') - $day, date('Y')),
                $end
            ];
        }
    
        /**
         * 返回几天前的时间戳
         *
         * @param int $day
         * @return int
         */
        public static function daysAgo($day = 1)
        {
            $nowTime = time();
            return $nowTime - self::daysToSecond($day);
        }
    
        /**
         * 返回几天后的时间戳
         *
         * @param int $day
         * @return int
         */
        public static function daysAfter($day = 1)
        {
            $nowTime = time();
            return $nowTime + self::daysToSecond($day);
        }
    
        /**
         * 天数转换成秒数
         *
         * @param int $day
         * @return int
         */
        public static function daysToSecond($day = 1)
        {
            return $day * 86400;
        }
    
        /**
         * 周数转换成秒数
         *
         * @param int $week
         * @return int
         */
        public static function weekToSecond($week = 1)
        {
            return self::daysToSecond() * 7 * $week;
        }
    
        private static function startTimeToEndTime()
        {
    
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Laravel 中操作 Redis

          本文链接:https://www.haomeiwen.com/subject/lobclqtx.html