当前位置:   article > 正文

Laravel-使用Redis-Bitmap签到_bitmap用户签到

bitmap用户签到

注:需求不一样则业务逻辑不一样

不说废话,直接干!!!!

Mysql:

CREATE TABLE `t_user_sign` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '用户ID',
  `days` int(11) NOT NULL COMMENT '累计签到天数',
  `year` int(11) NOT NULL COMMENT '年',
  `month` tinyint(4) NOT NULL COMMENT '月',
  `sign_record` varchar(255) NOT NULL COMMENT '签到记录',
  `last_sign_time` char(19) NOT NULL COMMENT '上次签到时间',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0-无效,1-有效',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1、控制器代码

    /**
     *  页面初始化,返回结果给前端
     */
    public function index()
    {
        $user_id = Request::input('user_id');
        $year = date('Y');
        $month = date('n');
        $signKey = 'sign_' . $year . '_' . $month . '_' . $user_id;
        $data = UserSignService::signDays($user_id,$signKey);
        $data['year'] = $year;
        $data['month'] = $month;
        return Utils::success($data);
    }


    /**
     *  签到/补签  这里使用了两种Redis数据类型,bitmap、hash
     */
    public function sign()
    {
        $user_id = Request::input('user_id');
        $type = Request::input('type',1); // 1、签到 , 2、补签
        $day = Request::input('day',0);
        if (!Utils::isValue($user_id)){
            return Utils::fail('无效user_id');
        }
        if ($type == 2){
            if (!Utils::isValue($day)){
                return Utils::fail('无效day');
            }
        }else{
            $day = Utils::getNowDay();
        }
        if ($day > Utils::getNowDay()){
            return Utils::fail('补签的日期不能大于等于今天');
        }

        $year = date('Y');
        $month = date('n');
        $signKey = 'sign_' . $year . '_' . $month . '_' . $user_id;

        $sign = Redis::getbit($signKey,$day);
        if ($type == 2){
            if (Utils::isValue($sign)){
                return Utils::success('您已补签,无需补签');
            }
        }else{
            if (Utils::isValue($sign)){
                return Utils::success('您今天已签到');
            }
        }

        Redis::setbit($signKey,0,1);
        Redis::setbit($signKey,$day,1);

        $data = UserSignService::signDays($user_id,$signKey);
        $datas = [
            'user_id' => $user_id,
            'days' => Utils::getValue($data,'days'),
            'year' => $year,
            'month' => $month,
            'sign_record' => Utils::getValue($data,'signDay'),
            'last_sign_time' => date('Y-m-d H:i:s')
        ];

        //  将用户的记录存放hash,到下个月初跑一次记录放进DB。注:需求不一样则业务逻辑不一样
        Redis::hset('sign_record',$user_id,json_encode($datas));
        //  缓存过期时间
        Redis::expire($signKey,3024000);
        Redis::expire('sign_record',3024000);

        if ($type == 2){
            return Utils::success('补签成功');
        }else{
            return Utils::success('签到成功');
        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

2、Service 代码

class UserSignService
{
    /**
     *  获取用户哪一天签到的? 和  签到总天数
     * @param $user_id  '用户ID'
     * @param $signKey  'key'
     * @return array
     */
    public static function signDays($user_id,$signKey): array
    {
        $bitmap_bin_str = self::strToBin(Redis::get($signKey));
        //调试使用,输出本月每天签到情况
        $month = date('t');
        $signDay = 0;
        for($i=1;$i<=$month;$i++) {
            if (empty($bitmap_bin_str[$i])) {
                $bitmap_bin_str[$i] = 0;
            }
            if ($bitmap_bin_str[$i] != 1) {
//                echo "$i 日未签到";
//                echo "<br>";
            } else {
                $signDay += 1;
//                echo "$i 日签到";
//                echo "<br>";
            }
        }

        return [
            'signDay' => substr($bitmap_bin_str,1),
            'days' => $signDay
        ];
    }


    /**
     *  转化数据
     * @param $str
     * @return string
     */
    public static function strToBin($str)
    {
        $arr = preg_split('/(?<!^)(?!$)/u', $str);
        foreach($arr as &$v){
            $temp = unpack('H*', $v);
            $v = base_convert($temp[1], 16, 2);
            unset($temp);
        }
        return join(' ',$arr);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

3、脚本command

public function handle()
    {
        $datas = Redis::hgetall('sign_record');
        foreach ($datas as $data){
            $data = json_decode($data);
            $user_id = Utils::getValue($data,'user_id');
            $where = [
                'user_id' => $user_id,
                'year' => date('Y'),
                'month' => date('n'),
            ];
            $userSignModel = UserSign::where($where)->first();
            if (Utils::isValue($userSignModel)){
                $userSignModel->toArray();
            }
            $userSignRecord = [
                'days' => Utils::getValue($data,'days'),
                'sign_record' => Utils::getValue($data,'sign_record'),
                'last_sign_time' => Utils::getValue($data,'last_sign_time')
            ];
            if (Utils::isValue($userSignModel)){
                DB::table('user_sign')->where($where)->update($userSignRecord);
            }else{
                $userSignRecord['user_id'] = Utils::getValue($data,'user_id');
                $userSignRecord['year'] = Utils::getValue($data,'year');
                $userSignRecord['month'] = Utils::getValue($data,'month');
                DB::table('user_sign')->insert($userSignRecord);
            }
        }

        echo '执行成功';

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

如有Command脚本不会的,自己私下百度。

列出执行命令:php artisan list

在这里插入图片描述

发现存在,即可执行,php artisan lesson:sign

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/382010
推荐阅读
相关标签
  

闽ICP备14008679号