程序版本:discuz!X1.5 X2 X2.5 X3 
目的:在线时间不更新或被恶意刷新解决办法 
适合人群:使用Discuz!系列的站长 
 
最近在论坛上出现了许多站点的用户在线时间,或者在线用户的列表出现错误数据。针对以上现象,我简单介绍下论坛更新在线时间和在线用户的机理。(以下针对X2版本,其他各个版本的原理基本相同)。 
 
 
所有的操作都在模板文件footer.htm中的一个不起眼的一条语句<!--{eval updatesession();}--> 
<!--{eval updatesession();}-->调用的是function_core.php中的updatesession函数。- function updatesession($force = false) {
 
  
-     global $_G;
 
 -     static $updated = false;
 
  
-     if(!$updated) {
 
 -         if($_G['uid']) {
 
 -             if($_G['cookie']['ulastactivity']) {
 
 -                 $ulastactivity = authcode($_G['cookie']['ulastactivity'], 'DECODE');
 
 -             } else {
 
 -                 $ulastactivity = getuserprofile('lastactivity');
 
 -                 dsetcookie('ulastactivity', authcode($ulastactivity, 'ENCODE'), 31536000);
 
 -             }
 
 -         }
 
 -         $discuz = & discuz_core::instance();
 
 -         $oltimespan = $_G['setting']['oltimespan'];
 
 -         $lastolupdate = $discuz->session->var['lastolupdate'];
 
  复制代码 $oltimespan = $_G['setting']['oltimespan'];对应的值是后台全局--站点功能--其他--用户在线时间更新时长(分钟)的值。- if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $ulastactivity) > $oltimespan * 60) {
 
 -             DB::query("UPDATE ".DB::table('common_onlinetime')."
 
 -                 SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "'
 
 -                 WHERE uid='{$_G['uid']}'");
 
 -             if(!DB::affected_rows()) {
 
 -                 DB::insert('common_onlinetime', array(
 
 -                     'uid' => $_G['uid'],
 
 -                     'thismonth' => $oltimespan,
 
 -                     'total' => $oltimespan,
 
 -                     'lastupdate' => TIMESTAMP,
 
 -                 ));
 
 -             }
 
 -             $discuz->session->set('lastolupdate', TIMESTAMP);
 
  复制代码 如果是会员登录论坛,判断最近更新时间与当前时间的差大于用户在线时间更新时长时,会更新pre_common_onlinetime表(记录会员在线时间)里对应用户的对应字段的值,若没有对应用户,则添加一条记录。-      foreach($discuz->session->var as $k => $v) {
 
 -             if(isset($_G['member'][$k]) && $k != 'lastactivity') {
 
 -                 $discuz->session->set($k, $_G['member'][$k]);
 
 -             }
 
 -         }
 
  
-         foreach($_G['action'] as $k => $v) {
 
 -             $discuz->session->set($k, $v);
 
 -         }
 
  
-         $discuz->session->update();
 
  
-         $updated = true;
 
  复制代码 然后程序开始更新session(针对所有用户,包括未登录的游客),将session数据存到pre_common_session表里。-  if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
 
 -             if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
 
 -                 $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);
 
 -             }
 
 -             dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
 
 -             DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
 
 -         }
 
 -     }
 
 -     return $updated;
 
 - }
 
  复制代码 最后根据用户最近的更新的时间,将计算出的用户在线时间,更新到pre_common_member_count表(统计用户记录信息表)里,我们看到的在线时间就是从此表里读取出来的,并且记录当前时间为用户最近活跃的时间。(注意:pre_common_member_count表中的在线时间是每12个小时更新一次) 
 
以上有两个关键点: 
在线时间的统计是由该函数执行和保存的,在线会员显示是直接读取的pre_common_session表中的数据 
 
在线时间问题解决方案: 
1.解决在线时间不更新的问题 
第1步.检查模板 
可能的原因是当前模板下footer.htm没有包含<!--{eval updatesession();}-->语句。 
可以选择手动在footer.htm中添加,或者用原foot.htm覆盖当前footer.htm文件。 
第2步.修改文件 
如果站点某些活跃用户出现在在线时间不更新的情况。为了不影响设计逻辑,照以下修改updatesession()函数: 
找到function_core.php的第66行附近- if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
 
 -             if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
 
 -                      $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);
 
 -              }
 
 -             dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
 
 -              DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
 
 - }
 
  复制代码 修改为- if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
 
 -           if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
 
 -                    $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);
 
  
-                    dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
 
 -           }                        
 
  
-         DB::update('common_member_status', array('lastip' => 
 
 - $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => 
 
 - TIMESTAMP), "uid='$_G[uid]'", 1);
 
 - }
 
  复制代码 2.解决用户刷在线时间 
同样是修改function_core.php中的updatesession函数 
找到- $lastolupdate = $discuz->session->var['lastolupdate'];
 
  复制代码 删除这句,将其替换成- $lastolupdate = DB::result_first("SELECT lastupdate FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
 
  复制代码 此方案解决用户刷在线时间,但已经刷过的用户,无法通过此方法恢复。 
 
本教程有无限星辰工作室www.xmspace.net整理发布 ,转载请注明地址! |