如今在很多应用或者公众号,类似于下图的百度签到(我每天都要去百度签到,还有阿里云学生优惠的签到),都有签到功能,签到给经验或者给积分,这是公司或者企业用以吸引用户,营销产品非常好的手段,而我在公司里面就经常遇到运营那边类似的需求,在这里我会进行实现该插件的分析。
百度签到
首先我们先分析,签到时候一般需要以下功能
1.每日签到,如果当天已经签到,则不能签到,得等到第二天才能签到
2.连续签到次数的统计,如果连续签到,连续签到次数归0.
3.签到完成积分(经验)的增加
然后我们再来分析实现这些功能,需要怎么去设计表,签到功能设计到用户,签到连续次数,所以这个签到表得有用户的id作为主键,以及签到次数这个字段,在这里我是这么设计这个表的
create TABLE `ds_youzan_signin`(
`uid` MEDIUMINT(7) PRIMARY KEY,
`time` char(12),
`days` int(6) DEFAULT 1,
`lasted` int(6) DEFAULT 1
);
uid:用户的id
time:签到时候的时间戳
days:签到的次数
lasted:连续签到天数
为什么会设计成上面那个样子,通过下面功能的分析,你就会明白了
功能1的实现
可能很多人一开始都会在想设计签到表,应该设置一个类型为enum的字段判断是否已经签到,签到了就设置为1,没有签到就设置为0,每到凌晨12点,就把全部用户的签到字段都改回0。我一开始也是那么分析,但是细想一下,你就会发现有很多问题。
1.很多语言没有定时功能,这时候可能很多同学就会想起使用linux的crontab命令,但是我感觉这样后面的人维护起来就不方便了,就算该语言有,应该也会挺耗费资源的。
2.如果有用户在此时(凌晨)进行操作,而你在清空数据,容易出现错误,我估计这就是百度签到不给凌晨一到就自动签到的缘故
那如何在不使用定时任务在凌晨清空数据的情况,知道该用户是否已经签到?其实很简单,只需要在签到的时候查看一下当前时间是否大于上次签到时间的凌晨,如果过了就证明没有签到。什么意思呢,举个例子,如果用户在 1号16:00:23 签到,则他在 2号12:01 就能签到,就是过了当天的凌晨就能签到了,所以我们只需要计算1号凌晨的时间戳,然后将1号凌晨的时间戳+一天时间秒数,即2号凌晨的时间戳(允许签到的时间界限),最后如果当前时间戳大于2号凌晨的时间戳,就证明是当前还没有签到。下面是图解,会更加清晰
下面是php实现流程
//获取当前时间戳
$now = time();
// 查询用户签到信息
$result = mysql_query("SELECT * FROM ds_youzan_signin WHERE uid={$uid}");
$signMes = mysql_fetch_assoc($result);
// 判断是否已经签到了,即现在时间大于上次签到时间的晚上12点
// 得出上次签到时间的年月日的凌晨,即 年:月:日 0
$y = date('Y',$signMes['time']);
$m = date('m',$signMes['time']);
$d = date('d',$signMes['time']);
// 上次签到日期凌晨转换为时间戳,即年:月:日 00:00:00
$allowTime= mktime(0,0,0,$m,$d,$y);
// 加上一天的秒数,即允许签到的时间界限
$allowTime += 3600*24;
// 过了允许签到的时间就给签到
if($allowTime <= $now){
// 还没有签到
return true;
}else{
// 已经签到
return false;
}
功能2的实现
相信经过功能1的分析,估计连续签到的功能,很多人都知道怎么实现了,还是根据上次签到日子的凌晨去判断。如果上次签到时间之后1天的凌晨大于当前签到时间,则证明是连续签到
至于每周排行榜,相信不用我说,大家都知道应该怎么实现了,直接根据那个时间戳的周日去判断