本帖最后由 dongdong0925 于 2011-4-28 19:11 编辑
更新的机制:如果当前时间 - 该用户的上一次更新时间(如果上一次更新时间不存在那么就是该用户最后的活动时间)>后台设置的用户在线时间更新时长*60,那么就会往common_onlinetime表里更新一下该用户的总在线时间和当月在线时间。如果当前时间 - 该用户的最后活动时间 > 43200(12个小时),那么就从common_onlinemember表里查询该用户的总在线时间更新到common_member_count表里的在线时间字段中。后台有一个清空本月在线时间的计划任务,每个月1日0点执行一次,清空所有用户当月的在线时间。
具体流程:
在template/common/footer.htm文件中可以找到这么一处代码。
- <!--{eval updatesession();}-->
复制代码
这个函数的定义在source/function/function_core.php文件中,具体代码如下:
- function updatesession($force = false) {
- global $_G;
- static $updated = false;
- if(!$updated) {
- $discuz = & discuz_core::instance();
- $oltimespan = $_G['setting']['oltimespan'];
- $lastolupdate = $discuz->session->var['lastolupdate'];
- if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $_G['member']['lastactivity']) > $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);
- }
- 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;
- if($_G['uid'] && TIMESTAMP - $_G['member']['lastactivity'] > 21600) {
- if($oltimespan && TIMESTAMP - $_G['member']['lastactivity'] > 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);
- }
- DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
- }
- }
- return $updated;
- }
复制代码 在updatesession()函数里进行了更新用户在线时间的操作,具体分析如下:
- $oltimespan = $_G['setting']['oltimespan'];
复制代码
$_G['setting']['oltimespan']就是后台定义的用户在线时间更新时长,单位为分钟,默认为10。具体设置的位置如图:
- $lastolupdate = $discuz->session->var['lastolupdate'];
复制代码
$discuz->session->var['lastolupdate']为该用户在session表记录的最后更新时间。
- 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,那么就执行{}里的操作。
- 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.
注意:这里每次更新都是在原来的基础上+用户在线时间更新时长。
- if(!DB::affected_rows()) {
- DB::insert('common_onlinetime', array(
- 'uid' => $_G['uid'],
- 'thismonth' => $oltimespan,
- 'total' => $oltimespan,
- 'lastupdate' => TIMESTAMP,
- ));
- }
复制代码
这句话的意思是如果上一条执行的语句没有返回影响的条数,那么就说明common_onlinetime这个表里还没有uid=$_G['uid']这条记录,那就往common_onlinetime表里新插入一条数据,其中的thismonth、total、lastupdate分别为当月在线时间、用户的总在线时间、上一次更新时间.
- $discuz->session->set('lastolupdate', TIMESTAMP);
复制代码
把session表里该用户的上一次更新时间字段更新为当前时间。
到这里往common_onlinetime表里更新在线时间的处理结束,下面看下是如何更新到用户表common_member_count表里的。
接着往下看代码,还是在updatesession()函数里,找到如下代码。
- if($_G['uid'] && TIMESTAMP - $_G['member']['lastactivity'] > 21600) {
- if($oltimespan && TIMESTAMP - $_G['member']['lastactivity'] > 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);
- }
- DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
- }
复制代码 $_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个小时)这个条件,满足就执行下面的操作。
- $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字段的值,即总在线时间。
- 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点执行一次,清空所有用户当月的在线时间,更新用户的当月在线时间。
|