每天给用户一个点数

5
使用PHP/mySQL,每天向用户的会员账户授予一个整数积分。我将使用以下mysql字段来确定是否应该授予积分:创建日期(时间戳)和上次登录(UNIX TIME)。
在用户登录时确定授予这些积分的程序。我的问题是,确定自上次登录以来过去了多少天最有效的方法是什么?其次,如果用户每天登录,如何确定是否已过去24小时并授予一个积分?过去的天数等于给定的积分(每天1个)。
目前,我正在使用以下代码:
/*
** Updates Points based on days since last visit
*/
static function UpdatePoints($username)
{
    $getlog = System::$mySQL->Select("lastLog, creation FROM users WHERE username='$username'");
    $log = System::$mySQL->Fetch($getlog);

    $offset = (TIME() - $log['lastLog']) / 86400;  // 24hrs
    $lastlog = round($offset); // in days

    if($lastlog > 0)
    {
        System::$mySQL->Update("users SET points=points+".$lastlog." WHERE username='$username'");
    }
}

除了标记之外,很明显我的代码是短视的。如果用户每天登录一次,他们不会获得积分。因此,我必须使用创建日期字段确定正确的方法。今天我无法理解它,有什么建议吗?谢谢。


也许在固定时间点,比如午夜时刻,授予积分会更容易些。对于那些在凌晨12:01注册的人来说,可能会稍微有些不公平,而相比之下,在11:59pm注册的人则会更加幸运。但是,经过几个月的会员资格后,这种差异就成为了一个舍入误差。 - Marc B
3
永远不要像你在这里所做的那样进行日期计算(即通过除以86400)。在任何一年中,都会有一个23小时的日子和一个25小时的日子。始终使用智能日期时间对象,否则会在程序中潜藏错误。 - riwalk
@Stargazer712 感谢您的提示,我从未考虑过。 - mrtwidget
2个回答

3

这个更适合存储在数据库中,而不是PHP代码中。添加一个名为users_points的表格,并创建唯一索引(user_id,login_date)。示例数据:

 user_id | login_date
====================== 
 19746   | 2010-09-02
 19746   | 2010-09-03

然后在每次登录时,标记用户已在该日期登录(如果该行已经存在,则索引将防止重复):

INSERT IGNORE INTO `users_points` (`user_id`,`login_date`) VALUES (19746,CURDATE())

要获取点数:

SELECT COUNT(*) FROM `users_points` WHERE `user_id` = 19746

如果您更改标准并想重新计算,用户登录日期列表也很有用。

user_id是一个INT,login_date是一个DATE,有一个可用的索引,因此插入和选择都应该很快,并且即使有大量用户,表格也会相对较小。

如果您坚持要将用户评分存储在某个位置(或者可能希望与其他用户数据一起检索),则可以在登录时执行以下操作:

  • 运行insert ignore
  • 运行select count
  • 将结果保存在表 users 的列中。

谢谢Piskvor!我认为你的回答改变了我的想法,不再进行所有这些计算,而是坚持使用表格。我一直沉迷于使用我已经拥有的东西,从未考虑过这个方向。如此简单明了(现在),却如此有效。谢谢! - mrtwidget
点数是一个经常被访问的值。每次需要计算它都是资源的浪费。必须定期执行一次计算,并从数据库中读取该值。 - Eugene Mayevski 'Callback
@Eugene Mayevski 'EldoS Corp:“点数是一个经常访问的值。”1)[需要引证] 2)如果您没有注意到,该值从数据库中读取的。3)与普遍预期相反,在类似这些情况下,索引非常有效。4)您是否建议对数据库进行去规范化?您是否遇到了显著的性能问题?(可能是这种情况,但我想看到一些数据;这个解决方案在数百万行上非常快) - Piskvor left the building
@Piskvor:你写道“要获取积分数量,使用select语句”。这是浪费资源。无论查询有多快,都只是额外的不必要工作,与拥有永久积分字段相比。现在,您还在污染数据库,添加了不必要的记录(登录日期)。您提议为每个用户保留多个记录,而不是为积分数量和上次登录日期保留两个字段。这是没有意义的。对于小表格,这将起作用,但如果在小事情上使用糟糕的设计,那么在真正重要的地方也会使用相同的糟糕设计。 - Eugene Mayevski 'Callback
1
@Eugene Mayevski 'EldoS Corp:如果你坚持认为这是糟糕的设计(该数字将从索引中检索,比逐行计数要快得多),那么你似乎不知道 MySQL 中选择优化和索引的相关内容(请参见链接)。如果你真的非常想在某个地方存储得分,请在 insert ignore 后立即执行 select count... 并将结果存储在 users 中。编辑答案时已经加入了这部分信息。http://dev.mysql.com/doc/refman/5.0/en/where-optimizations.html - Piskvor left the building
显示剩余2条评论

3

使用单独的字段来保存您将积分添加到用户账户的日期。如果这不是今天发生的,请添加一个或多个点并更新该字段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接