PHP用戶連續簽到贈送額外積分

一、需求

1、爲什麼要贈送積分

用戶(連續)簽到贈送(額外)積分,可以增加用戶的活躍度,少一些殭屍用戶;邀請好友贈送積分,可以擴大平臺的用戶量。

2、怎麼獲取積分

這個範圍就比較廣了,給幾個獲取積分的例子

  • 用戶註冊獲取積分
  • 成功邀請新用戶獲取積分
  • 完成首購獲取積分
  • 用戶消費獲取積分
  • 用戶簽到獲取積分
  • 完成新手任務獲取積分
  • 完善基本信息獲取積分

3、積分如何使用

1)、兌換

  • 可以弄個積分商城,直接用積分兌換商品

2)、抵扣

  • 購買商品時,除了可以使用優惠券抵扣、餘額抵扣,還可以使用積分抵扣

3)、等等

二、規則

1、用戶註冊

  • 用戶註冊贈送積分

2、成功邀請新用戶

  • 成功邀請新用戶,新用戶有註冊積分,邀請人有邀請積分

3、用戶簽到

  • 用戶每日簽到可以獲取固定的積分
  • 用戶連續簽到滿n天,額外贈送積分
  • 如果用戶同時滿足多個連續簽到任務,則取額外積分爲最大簽到天數的積分
    • 多個簽到任務:比如用戶連續5天贈送1積分,用戶連續簽到10天贈送2積分;用戶連續簽到了10天,則既滿足連續簽到5天,又滿足連續簽到10天,我們取連續簽到10天的2積分作爲額外積分。(也可以都取,則額外積分爲1+2=3,這個要看規則怎麼定了)

4、聯想

  • 可以添加規則用戶簽到當天如果是用戶生日,積分翻倍
    • Tips:如果生日可爲公曆,也可爲農曆,則要注意區分

三、數據表

1、用戶表 user

`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
...
`integral` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '總積分',
`signDay` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '連續簽到天數',
`createTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`updateTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',

2、用戶簽到表 user_sign

`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`userId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`integral` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '積分',
`dateTime` varchar(50) NOT NULL DEFAULT '' COMMENT '簽到日期:格式爲2090-01-01',
`remark` text COMMENT '備註',
`createTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`updateTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',

3、積分(獲取)日誌表 integral_log

`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`userId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`fkId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '關聯id',
`fkType` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '關聯類型:1:新用戶註冊;2用戶簽到;3用戶消費;4邀請新用戶;...',
`integral` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '積分',
`remark` text COMMENT '備註',
`createTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`updateTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',

四、代碼

1、用戶簽到方法

/**
 * 用戶簽到
 * @return mixed
 * @throws Exception
 */
public function sign() {
    $userInfo = self::loginInfo();  //緩存中根據Token獲取用戶的登錄信息
    if (!$userInfo){
        exit('請先登錄');
    }
    $userId = $userInfo['id'];

    $userDao = new UserDao();       //實例化用戶表
    $signDao = new UserSignDao();   //實例化用戶簽到表

    //判斷用戶今天是否簽到
    $dateTime = date('Y-m-d');
    $todayParam = ['userId' => $userId, 'dateTime' => $dateTime];
    $todayInfo = $signDao->single($todayParam);
    if ($todayInfo){
        exit('您今天已經簽到過了');
    }

    //判斷用戶昨天是否簽到
    $yesterday = date('Y-m-d', strtotime('-1 day'));    //昨天的日期格式:2090-01-01
    $yesterdayParam = ['userId' => $userId, 'dateTime' => $yesterday];
    $yesterdayInfo = $signDao->single($yesterdayParam);
    if ($yesterdayInfo){    //昨天簽到了,簽到天數自增1
        $userDao->setInc(['id' => $userId], 'signDay', 1);  //第三個參數默認爲1,可以不傳。
    }else{  //昨天斷籤,連續簽到天數重置爲1
        $userDao->updateByQuery(['signDay' => 1], ['id' => $userId]);  //更新該用戶的簽到天數爲1天
    }

    list($integral, $remark) = IntegralService::insert($userId, 2);    //記錄簽到積分日誌

    //添加簽到數據
    $data = [
        'userId' => $userId,        //用戶ID
        'dateTime' => $dateTime,    //簽到日期
        'integral' => $integral,    //簽到贈送的積分
        'remark' => $remark         //簽到日誌
    ];
    $signDao->insert($data);        //添加數據,createTime,updateTime已在該方法中追加

    return 'success';
}

2、公共類 - 積分贈送日誌方法

  • 這個表可以再加個type字段,區分積分類型:積分獲取/積分消費
class IntegralService{
    /**
     * [積分贈送日誌]公共方法
     * @param $userId 用戶ID
     * @param $fkType 贈送類型:1:新用戶註冊;2用戶簽到;3用戶消費;4邀請新用戶;...
     * @param int $fkId 關聯ID:如果類型爲用戶消費,則關聯ID爲訂單的ID;如果類型爲邀請新用戶,則關聯ID爲新用戶的ID...
     * @return array 返回[積分,備註]
     */
    public static function insert($userId, $fkType, $fkId = 0){
        $remark = '';
        $integral = 0;
        $userDao = new UserDao();

        if ($fkType == 1){  //新用戶註冊
            $integral = 20; //新用戶註冊贈送積分:這個可以寫到配置裏
            $remark = '新用戶贈送積分';
        }else if ($fkType == 2){    //每日簽到贈送額外積分
            list($integral, $remark) = self::userSign($userId, $userDao);
        }else if ($fkType == 3){    //消費
            //...
        }else if ($fkType == 4){    //推薦新用戶
            $userInfo = $userDao->info($fkId);  //新用戶的ID
            if (empty($userInfo)){
                exit('被邀請用戶不存在');
            }
            $integral = 10; //推薦新用戶註冊贈送積分:這個可以寫到配置裏
            $remark = '邀請新用戶 [ ' . $userInfo['username'] . ' ] 贈送積分';
        }

        //積分日誌記錄
        $data = [
            'userId' => $userId,
            'fkId' => $fkId,
            'fkType' => $fkType,
            'integral' => $integral,
            'remark' => $remark
        ];
        $integralDao = new IntegralLogDao();
        $integralDao->insert($data);    //添加數據,createTime,updateTime已在該方法中追加

        //用戶積分自增$integral
        $userDao->setInc(['id' => $userId], 'integral', $integral);

        return [$integral, $remark];
    }

    /**
     * 獲取會員簽到獲取的積分,備註
     * @param $userId
     * @param $userDao
     * @return array
     */
    public static function userSign($userId, $userDao){
        $userInfo = $userDao->info($userId);
        if (empty($userInfo)){
            exit('用戶不存在');
        }
        $signDay = $userInfo['signDay'];   //用戶連續簽到天數

        $remark = '';
        $integral = 3;  //用戶每日簽到積分:這個可以寫到配置裏
        if ($signDay != 0){ //如果簽到日期不爲0
            # 簽到額外送積分:這個可以寫到配置裏
            /**
             * name:說明
             * desc:備註,這裏表示連續簽到天數
             * value:值,這裏表示額外贈送積分數量
             */
            $extraIntegral = [
                ['name' => '連續簽到7天額外贈送1積分', 'desc' => 7, 'value' => 1],
                ['name' => '連續簽到15天額外贈送2積分', 'desc' => 15, 'value' => 2],
                ['name' => '連續簽到30天額外贈送5積分', 'desc' => 30, 'value' => 5],
            ];

            //二維數組排序:按照積分降序,如果同時滿足多個連續簽到任務,則取最大簽到天數的積分。
            $values = array_column($extraIntegral, 'value');
            array_multisort($values, SORT_DESC, $extraIntegral);

            $isGiveExtra = false;                   //是否已經贈送了額外積分
            foreach ($extraIntegral as $value){
                $day = $value['desc'];              //配置的簽到天數
                $giveIntegral = $value['value'];    //贈送額外積分
                if (($signDay % $day) == 0){        //如果:用戶連續簽到天數 % 配置的連續簽到天數 = 0;我們認爲該用戶可以獲取額外積分
                    if ($isGiveExtra){              //如果:已經贈送了額外積分,則不再贈送,結束循環
                        break;
                    }
                    $integral += $giveIntegral;     //積分 = 每日簽到默認積分 + 連續簽到額外贈送的積分
                    $remark = "您已經連續簽到了 [ {$day} ] 天,額外贈送您 [ {$giveIntegral} ] 積分"; //備註
                    $isGiveExtra = true;            //設置爲true,已經贈送了積分,不再重複贈送
                    # 或者去除 $isGiveExtra 變量相關操作,直接在這裏 break
                }
            }
        }
        $remark = $remark ? $remark : '簽到贈送積分';

        return [$integral, $remark];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章