首页
站长论坛BBS
救助
投稿
discuz视频教程
discuz技术支持
版块
登录
快速注册

为什么Discuz! X会员在线时间不更新,解析dz在线时间机制

建站高手 2015-6-30 [Discuz开发] 来自PC 复制链接
415432
discuz使用视频教程
31idc

马上注册,一起探讨正确快速的建站方法

您需要 登录 才可以下载或查看,没有帐号?快速注册

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



discuz! X会员在线时间更新具体流程:

在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')."
  2. SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "'
  3. 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点执行一次,清空所有用户当月的在线时间,更新用户的当月在线时间。



上一篇:如何copy别人的diy首页模板呢
下一篇:Discuz x论坛附件或图片上传flash分析讲解 二次开发可看
tinsn 发表于 2015-7-1 10:07:24 来自PC
真心高手。官网倒了,还有站帮在
小美--肿么了 发表于 2015-7-1 22:13:38 来自PC
以下网站跟你做交换。 朋友, 你看看呢:
http://www.lljh998.com
http://www.xsfgoods.com
http://www.aiqingshui.com
www.sby886.com www.cnm982.com
洋洋 发表于 2015-7-2 11:19:31 来自PC
强烈支持,站帮网有你更精彩
http://www.02lx.com http://www.xcyy0451.com
awy123 发表于 2015-7-3 10:18:44 来自PC
  
楼主辛苦了 。。
www.hbcsdzqc.com
www.hbcsdzqc.com随车吊_起重机
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

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