Discuz!官方免费开源建站系统

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

解析Discuz! X1.5更新在线时间的机制

[复制链接]
dongdong0925 发表于 2011-4-28 19:11:46 | 显示全部楼层 |阅读模式
本帖最后由 dongdong0925 于 2011-4-28 19:11 编辑

更新的机制:如果当前时间 - 该用户的上一次更新时间(如果上一次更新时间不存在那么就是该用户最后的活动时间)>后台设置的用户在线时间更新时长*60,那么就会往common_onlinetime表里更新一下该用户的总在线时间和当月在线时间。如果当前时间 - 该用户的最后活动时间 > 43200(12个小时),那么就从common_onlinemember表里查询该用户的总在线时间更新到common_member_count表里的在线时间字段中。后台有一个清空本月在线时间的计划任务,每个月1日0点执行一次,清空所有用户当月的在线时间。

具体流程:

在template/common/footer.htm文件中可以找到这么一处代码。
  1. <!--{eval updatesession();}-->
复制代码

这个函数的定义在source/function/function_core.php文件中,具体代码如下:


  1. function updatesession($force = false) {

  2.         global $_G;
  3.         static $updated = false;
  4.         if(!$updated) {
  5.                 $discuz = & discuz_core::instance();
  6.                 $oltimespan = $_G['setting']['oltimespan'];
  7.                 $lastolupdate = $discuz->session->var['lastolupdate'];
  8.                 if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $_G['member']['lastactivity']) > $oltimespan * 60) {
  9.                         DB::query("UPDATE ".DB::table('common_onlinetime')."
  10.                                 SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "'
  11.                                 WHERE uid='{$_G['uid']}'");
  12.                         if(!DB::affected_rows()) {
  13.                                 DB::insert('common_onlinetime', array(
  14.                                         'uid' => $_G['uid'],
  15.                                         'thismonth' => $oltimespan,
  16.                                         'total' => $oltimespan,
  17.                                         'lastupdate' => TIMESTAMP,
  18.                                 ));
  19.                         }
  20.                         $discuz->session->set('lastolupdate', TIMESTAMP);
  21.                 }
  22.                 foreach($discuz->session->var as $k => $v) {
  23.                         if(isset($_G['member'][$k]) && $k != 'lastactivity') {
  24.                                 $discuz->session->set($k, $_G['member'][$k]);
  25.                         }
  26.                 }

  27.                 foreach($_G['action'] as $k => $v) {
  28.                         $discuz->session->set($k, $v);
  29.                 }

  30.                 $discuz->session->update();

  31.                 $updated = true;

  32.                 if($_G['uid'] && TIMESTAMP - $_G['member']['lastactivity'] > 21600) {
  33.                         if($oltimespan && TIMESTAMP - $_G['member']['lastactivity'] > 43200) {
  34.                                 $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
  35.                                 DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);
  36.                         }
  37.                         DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
  38.                 }
  39.         }
  40.         return $updated;
  41. }
复制代码
在updatesession()函数里进行了更新用户在线时间的操作,具体分析如下:

  1. $oltimespan = $_G['setting']['oltimespan'];
复制代码

$_G['setting']['oltimespan']就是后台定义的用户在线时间更新时长,单位为分钟,默认为10。具体设置的位置如图:


  1. $lastolupdate = $discuz->session->var['lastolupdate'];
复制代码

$discuz->session->var['lastolupdate']为该用户在session表记录的最后更新时间。

  1. if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $_G['member']['lastactivity']) > $oltimespan * 60) {
复制代码


这里重点讲下这个if判断里的TIMESTAMP - ($lastolupdate ? $lastolupdate : $_G['member']['lastactivity']) > $oltimespan * 60这个条件:
$_G['uid']:用户uid
TIMESTAMP: 当前服务器时间
$lastolupdate: 用户的上一次更新时间
$_G['member']['lastactivity']:用户最后的活动时间
$oltimespan:用户在线时间更新时长

($lastolupdate ? $lastolupdate : $_G['member']['lastactivity']) 这是一个三元表达式,如果存在$lastolupdate那么就是$lastolupdate,如果不存在那么就是$_G['member']['lastactivity']。

所以这个条件的意思就是:
如果当前时间 - 用户的上一次更新时间或者用户的最后活动时间 > 用户在线时间更新时长*60,那么就执行{}里的操作。

  1. DB::query("UPDATE ".DB::table('common_onlinetime')."                                SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "'                                WHERE uid='{$_G['uid']}'");
复制代码
这句代码的意思是根据uid=$_G['uid']往common_onlinetime表里更新该用户的总在线时间total,当月在线时间thismonth,上一次更新时间lastupdate.

注意:这里每次更新都是在原来的基础上+用户在线时间更新时长。

  1. if(!DB::affected_rows()) {
  2.                                 DB::insert('common_onlinetime', array(
  3.                                         'uid' => $_G['uid'],
  4.                                         'thismonth' => $oltimespan,
  5.                                         'total' => $oltimespan,
  6.                                         'lastupdate' => TIMESTAMP,
  7.                                 ));
  8.                         }
复制代码


这句话的意思是如果上一条执行的语句没有返回影响的条数,那么就说明common_onlinetime这个表里还没有uid=$_G['uid']这条记录,那就往common_onlinetime表里新插入一条数据,其中的thismonth、total、lastupdate分别为当月在线时间、用户的总在线时间、上一次更新时间.



  1. $discuz->session->set('lastolupdate', TIMESTAMP);
复制代码


把session表里该用户的上一次更新时间字段更新为当前时间。

到这里往common_onlinetime表里更新在线时间的处理结束,下面看下是如何更新到用户表common_member_count表里的。

接着往下看代码,还是在updatesession()函数里,找到如下代码。
  1. if($_G['uid'] && TIMESTAMP - $_G['member']['lastactivity'] > 21600) {
  2.                         if($oltimespan && TIMESTAMP - $_G['member']['lastactivity'] > 43200) {
  3.                                 $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
  4.                                 DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);
  5.                         }
  6.                         DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
  7.                 }
复制代码
$_G['uid']:用户uidTIMESTAMP:当前服务器时间
$_G['member']['lastactivity']:用户的最后活动时间
$oltimespan:用户在线时间更新时长

if($_G['uid'] && TIMESTAMP - $_G['member']['lastactivity'] > 21600) {
首先判断是否存在uid,同时是否满足当前时间 - 用户的最后活动时间 > 21600(21600/3600=6个小时)这个条件,满足就执行{}里的操作。

if($oltimespan && TIMESTAMP - $_G['member']['lastactivity'] > 43200) {
判断是否存在$oltimespan,同时是否满足当前时间 - 用户的最后活动时间 > 43200(43200/3600=12个小时)这个条件,满足就执行下面的操作。
  1. $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);
复制代码
首先查询common_onlinetime表里uid=$_G['uid']的用户的总在线时间,然后更新到common_member_count表里。

这里说明下:common_onlinetime表里记录的时间是以分钟为单位,common_member_count表里是以小时为单位。我们在前台页面看到的用户在线时间就是common_member_count表里的oltime字段的值,即总在线时间。

  1. DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
复制代码

更新common_member_status表里uid=$_G['uid']的最后访问的IP、最后的活动时间、最后的活动时间。




由于每个页面都会加载footer.htm文件,同时又会加载updatesession()函数,这样每次访问都会判断用户的在线时间是否需要更新。
总的来说,在线时间的更新就是先更新到common_onlinetime表里,然后当满足当前时间-最后活动时间>12个小时的话再更新到common_member_count表中的在线时间。同时后台有一个清空本月在线时间的计划任务,每个月1日0点执行一次,清空所有用户当月的在线时间,更新用户的当月在线时间。



楚一 发表于 2011-4-28 19:28:59 | 显示全部楼层
顶冬冬
回复

使用道具 举报

0833hy 发表于 2011-4-28 23:43:27 | 显示全部楼层
www.0833hy.com
前排支持DZ
回复

使用道具 举报

小足球 发表于 2011-4-29 00:07:00 | 显示全部楼层
请问VPS如何设置目录的读写属性
回复

使用道具 举报

marco129 发表于 2011-4-29 14:51:56 | 显示全部楼层
回复

使用道具 举报

pcyi 发表于 2011-5-3 07:23:49 | 显示全部楼层
前排支持DZ。
回复

使用道具 举报

SPITZ 发表于 2011-5-6 13:18:01 | 显示全部楼层
没看懂。。。
回复

使用道具 举报

滚雪球 发表于 2011-5-7 13:59:01 | 显示全部楼层
这么长一段,没看懂。
回复

使用道具 举报

无忧虾 发表于 2011-5-7 17:45:07 | 显示全部楼层
长,没看懂。
回复

使用道具 举报

国狼策略 发表于 2011-5-13 22:20:08 | 显示全部楼层
占位观看
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|Discuz! 官方站 ( 皖ICP备16010102号 )star

GMT+8, 2024-11-15 19:27 , Processed in 0.035234 second(s), 6 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表