天天看點

Discuz中session機制流程圖以及心得

下面這個流程圖是我在網上找到的,順着流程圖,可以更深入的學習discuz的session機制

Discuz中session機制流程圖以及心得

當初始化application時,對session進行初始化。代碼主要實作以下功能:

1.判斷session狀态是否為開啟,開啟則繼續

2.将cookie下的sid指派給session中 sid,保持session和cookie中的sid保持相同。當session中的sid和cookie的sid不一緻或者sid不存在,則重新建立sid,并更新cookie。

3.擷取上次使用者活動狀态,如果未登入,則将使用者組設定為遊客并關聯ip。如果登入,記錄使用者上次登入時間和ip。

代碼如下:source/class/discuz/discuz_application.php

private function _init_session() {

		$sessionclose = !empty($this->var['setting']['sessionclose']);
		$this->session = $sessionclose ? new discuz_session_close() : new discuz_session();

		if($this->init_session)	{
			$this->session->init($this->var['cookie']['sid'], $this->var['clientip'], $this->var['uid']);
			$this->var['sid'] = $this->session->sid;
			$this->var['session'] = $this->session->var;

			if(!empty($this->var['sid']) && $this->var['sid'] != $this->var['cookie']['sid']) {
				dsetcookie('sid', $this->var['sid'], 86400);
			}

			if($this->session->isnew) {
				if(ipbanned($this->var['clientip'])) {
					$this->session->set('groupid', 6);
				}
			}

			if($this->session->get('groupid') == 6) {
				$this->var['member']['groupid'] = 6;
				if(!defined('IN_MOBILE_API')) {
					sysmessage('user_banned');
				} else {
					mobile_core::result(array('error' => 'user_banned'));
				}
			}

			if($this->var['uid'] && !$sessionclose && ($this->session->isnew || ($this->session->get('lastactivity') + 600) < TIMESTAMP)) {
				$this->session->set('lastactivity', TIMESTAMP);
				if($this->session->isnew) {
					if($this->var['member']['lastip'] && $this->var['member']['lastvisit']) {
						dsetcookie('lip', $this->var['member']['lastip'].','.$this->var['member']['lastvisit']);
					}
					C::t('common_member_status')->update($this->var['uid'], array('lastip' => $this->var['clientip'], 'port' => $this->var['remoteport'], 'lastvisit' => TIMESTAMP));
				}
			}

		}
	}
           

建立sid代碼:source/class/discuz/discuz_session;

public function create($ip, $uid) {
		$this->isnew = true;
		$this->var = $this->newguest;
		$this->set('sid', random(6));
		$this->set('uid', $uid);
		$this->set('ip', $ip);
		$uid && $this->set('invisible', getuserprofile('invisible'));
		$this->set('lastactivity', time());
		$this->sid = $this->var['sid'];
		return $this->var;
	}
           

在論壇開發或者模版制作中,比較關心的session是使用者線上時長和使用者登入狀态記錄。

關于線上時長的知識,請參考:為什麼Discuz! X會員線上時間不更新,解析dz線上時間機制

看了discuz的session機制,有一點拙見:

為什麼我們要用資料庫來記錄session狀态呢?

我覺得一來是資料庫可以實作持久化的效果。二來,對于一個大中型的網站,例如社交網站,或電商網站,需要一個穩定的狀态共享的確定。就像一個人的旅行,他将所有的現金集中放到銀行,每到達一個目的地的時候,如果需要就可以很友善的僅僅使用銀行卡就可以解決金錢問題,也可以在旅途中将額外的金錢随時存入銀行。這樣的目的,使得他能在不同時刻不同地點來進行金錢的存取,即使說有一天他身上取出的現金丢了,也可以使用銀行卡來保證剩下的旅途的金錢保障。大的網站會将session獨立出來,放置在專用的伺服器上,當分布系統有當機出現,備用的容錯系統就可以很快的恢複到之前的狀态。當然這一個過程需要很多方面的支援才行,這裡隻是一個很小的session部分。

而就discuz的session中,session記錄表中隻記錄一些初始的狀态,更多的都是使用cookie來記錄。這和discuz的服務對象是分不開的,假如當有一天,discuz成了shopnc,session能實作的就遠遠不止記錄目前狀态這麼少了。

繼續閱讀