我正在编写一个用户系统,作为所有用户可用的统计数据,我希望能够向他们提供他们在我的网站上活跃的时间。
我最初的想法是:user加载页面,用户的记录存储在名为accessLog的SQL表中*用户加载另一个页面,SQL查询运行,看看他们最后一次访问的页面*如果用户在过去两分钟内访问了一个页面,则更新其用户帐户并添加在线时间*在accessLog中插入一条新记录*
然而,这将意味着增加4个额外的查询到我的网站的每一个页面的潜力,这似乎很慢。我在想,一定有一种更有效的方法来跟踪用户的在线活动,而我显然太笨了,看不到!
- 当用户加载一个页面时,他们的"最后一个页面加载时间"在数据库中更新。
- 每分钟运行一个cron脚本。它查找"最后一个页面加载时间"在最后一分钟的用户。
- 为每个找到的用户增加"在站点上花费的时间"。
通过这种方式,我可以精确到分钟地跟踪用户。除以60就得到小时数。
我会使用ajax让客户端每分钟调用一次服务器。只是告诉服务器用户还在看那个页面。
-
服务器将在数据库中有一个lastTimestamp和一个totalTimeSpentOnSite。lastTimestamp只包含ajax请求或页面加载的最后一次时间。
-
每次ajax触发时,服务器将计算
now - lastTimestamp
并将其添加到totalTimeSpentOnSite.
为了更准确,你可以
向onBlur()
添加javascript侦听器,只记录该窗口活动的实际时间,然后将该时间发送到服务器,而不仅仅是告诉服务器用户仍然活动。
我的哲学是:不要过分关注效率,直到它成为一个问题。除非你的网站流量很大,否则你不会注意到这四个查询。这可能更简单:
- 记录每次页面加载。
- 每隔几个小时,通过cron运行一个计算时间的脚本每个用户的在线花费,并更新该用户的运行总数表。
- 定期清空access_log表
将其添加到会话管理中。当用户开始会话时,记录他们的开始时间。当用户结束会话时,记录其结束时间。通过简单的计算,你就能得到他们每次在你网站上花费的时间。
回答philip Haglund
是的,但是你必须等待会话超时,而这个时间并不能反映用户在他/她关闭前在最后一个页面上花费的实际时间。
这是真的,但是,到目前为止,所有可用的答案都是在相同的基本前提下工作的:
- 记录页面加载时间
- 用户离开 时的日志
- 更新数据库表
当用户离开时,恰好需要记录会话。我不知道PHP中还有什么其他方式可以像OP希望的那样跟踪用户活动。更新数据库表是一个技术问题。您想使用CRON作业吗?您想使用AJAX吗?你想做点别的吗?
如果你真的想知道实际发生了多少活动,你可以为某些JavaScript事件发送AJAX请求。这将把时间跟踪与实际的浏览器事件联系起来。当然,这意味着您的时间跟踪依赖于启用JavaScript。
"两分钟"规则有点不可靠——你可能会被试图弄清楚"花时间"的实际含义所束缚。
在上一个项目中,我们做了以下工作。
在每次页面加载时,我们检查用户是否有当前会话,如果没有,则创建一个GUID来标识当前会话。
我们向数据库写入了一条日志记录,其中包含日期时间、GUID、页面URL和用户ID(如果用户已经登录)。
为了计算"花费的时间",我们计算会话GUID的第一条和最后一条记录之间的时间差,并添加一分钟来反映在最后一页上花费的时间。
这并不完全准确,但是对于流量适中的站点,它可以实时运行而不需要CRON。
- 首先选择会话被认为中断的持续时间。(例如:10分钟)
- 记录所有页面加载与所有ip在数据库
- 如果一个ip的两个页面加载之间的时间超过持续时间,则不将此时间添加到该ip的总时间
- 如果一个ip的两个页面加载之间的时间小于持续时间,将此时间添加到该ip的总时间
2的问题是:-如果用户停留超过持续时间(10分钟)在一个页面没有刷新,他被认为是断开连接。-最后一页持续时间不保存
Piwik是这样工作的
这就是我使用的,它在用户加载任何页面时检查更新DB。数据是准确的,因为它计算用户是否每分钟加载一个页面,如果是,它将时间差添加到数据库中。
$now= time();
$stmt = $db_con->prepare(" SELECT last_seen,time_online FROM user_online_log WHERE user_id=? limit ? ");
$stmt->execute(array( $user_id, 1));
$fetch= $stmt->fetch(PDO::FETCH_ASSOC);
$last_seen=$fetch['last_seen']; //integer value from db, saved from time() function
$last_seen_plus_one_min= $last_seen + 60;
if( $now < $last_seen_plus_one_min ){
$additional_time_online= $now - $last_seen; }
else{ $additional_time_online = 0; }
//update db
$stmt12 = $db_con->prepare(" update user_online_log set last_seen=?, time_online = time_online+? WHERE user_id=? limit 1 ");
$stmt12->execute(array($now, $additional_time_online, $user_id));