流程結構(隨便找個地址來分析下,好比 設置 -> 我的資料 -> 聯繫方式;地址是:home.php?mod=spacecp&ac=profile&op=contact)php
(一)首先打開home.php文件 看到第17行mysql
1
|
require_once
'./source/class/class_core.php'
;
|
我同時打開了多個入口的文件都有這麼一個引入,所以能夠確定這是個入口配置文件,負責文件引入及初始化須要的組件,下面來看下這個文件 sql
第10行 error_reporting(E_ALL); 報告全部錯誤數據庫
第12-15行四個常量定義數組
1
2
3
4
|
define(
'IN_DISCUZ'
, true);
define(
'DISCUZ_ROOT'
,
substr
(dirname(
__FILE__
), 0, -12));
define(
'DISCUZ_CORE_DEBUG'
, false);
define(
'DISCUZ_TABLE_EXTENDABLE'
, TRUE);
|
第17-22行設置異常處理函數緩存
1
2
3
4
5
6
|
set_exception_handler(
array
(
'core'
,
'handleException'
));
if
(DISCUZ_CORE_DEBUG) {
set_error_handler(
array
(
'core'
,
'handleError'
));
register_shutdown_function(
array
(
'core'
,
'handleShutdown'
));
}
|
第24-30行設置類自動引入的處理函數(這裏看仔細,很重要)cookie
1
2
3
4
5
6
7
|
if
(function_exists(
'spl_autoload_register'
)) {
spl_autoload_register(
array
(
'core'
,
'autoload'
));
}
else
{
function
__autoload(
$class
) {
return
core::autoload(
$class
);
}
}
|
第32行 初始化core類session
1
|
C::creatapp();
|
這個C是core類的映射,證據是第208行 app
1
|
class
C
extends
core {}
|
來看靜態方法creatapp() xss
1
2
3
4
5
6
|
public
static
function
creatapp() {
if
(!
is_object
(self::
$_app
)) {
self::
$_app
= discuz_application::instance();
}
return
self::
$_app
;
}
|
咱們看到是返回了一個屬性,這個屬性_app 是discuz_application::instance()的返回值,咱們來看discuz_application類,從上面的自動引入中咱們看到這個類的地址是 ./source/class/discdz/discdz_application.php,
來看剛纔執行的靜態方法 discuz_application::instance() 的返回值是個啥?
1
2
3
4
5
6
7
|
static
function
&instance() {
static
$object
;
if
(
empty
(
$object
)) {
$object
=
new
self();
}
return
$object
;
}
|
原來是按址引用的,而且是實理化自身了,這個類繼承自抽象類discuz_base,這個應該是個基類,來看看構造函數。
1
2
3
4
5
6
|
public
function
__construct() {
$this
->_init_env();
//274-316行;初始化環境變量。定義了些常量,引入了公共函數庫,在./source/function/function_core.php,設置最小內存128M。並設置了容許的全局變量(_GET,_POST,_REQUEST,_COOKIE,_SERVER,_ENV,_FILES),定義了一個全局變量$_G,變將這個全局變量按址傳遞給了$this->var,看來在模板中能夠直接使用這些變量的。
$this
->_init_config();
//274-316行;初始化配置變量。引入了配置,在./config/config_global.php,將配置變量所有壓入到$this->var['config']中,在全局均可以使用配置啦
$this
->_init_input();//224-272行;初始化輸入。過濾了下全局變量($_GET['GLOBALS'],$_POST['GLOBALS']……),若是開啓了get_magic_quotes_gpc(),就給$_GET,$_POST,$_COOKIE變量stripslashes一下,設置合法的cookie的鍵名必須 $this->config['cookie']['cookiepre']這個開頭的,在配置文件中有。這樣作應該是防止非法cookie變量,243行把$_POST的值合併到$_GET變量中去。把rawurlencode($_GET['page'])編碼下,過濾了下$_GET['handlekey'],過濾$_GET變量, foreach($_GET as $k => $v) {$this->var['gp_'.$k] = daddslashes($v);}使用的是stripslashes函數。另外設置了幾個全局變量 $this->var['XXX']本身瞅瞅。
$this
->_init_output();//318-345行;初始化輸出。過濾URL$this->_xss_check();<"CONTENT-TRANSFER-ENCODING都是非法的。若是控制器爲'seccode', 'secqaa', 'swfupload'則進行這個過濾,有時間看看./source/include/misc/misc_security.php;開啓ob_start(),設置charset;
}
|
好了,如今咱們明白了,咱們如今獲得了一個對象C,而且它有一個屬性叫_app,這個屬性是discuz_application對象,再在回到入口配置文件class_core.php,下面執行到了第209行,咱們看到一個映射
1
|
class
DB
extends
discuz_database {}
|
DB表明了discuz_database對象,咱們去看看這個對象。從上面的自動引入類機制中咱們獲得了這個類位於 ./source/class/discdz/discdz_application.php。打開看看,原來是數據庫操做的;靜態方法 init($driver, $config)應該是初始化這個類的方法,從字面意思看,傳兩個參數進來,第一個參數是數據庫驅動,第二個參數是數據庫鏈接參數,之後的數據庫操做應該都是DB::update() DB::delete這樣的方法了。
好了,跟着程序運行順序走,咱們如今返回到入口文件home.php第18行
1
|
require_once
'./source/function/function_home.php'
;
|
進去看看,原來是一組函數,這是個函數庫,瞄了兩眼,如今回到home.php第20行
1
|
$discuz
= C::app();
|
原來是把discuz_application對象賦值給變量$discuz。
到第22-24行
1
2
3
|
$cachelist
=
array
(
'magic'
,
'userapp'
,
'usergroups'
,
'diytemplatenamehome'
);
$discuz
->cachelist =
$cachelist
;
$discuz
->init();
|
哇靠,$discuz->init();這一行纔是核心中的核心,具體功能是初始化整個discuz應用。discuz_application類是整個discuz的應用初始化類,至關於織夢的 /include/common.inc.php的功能
1
2
3
4
5
6
7
8
9
10
11
12
|
public
function
init() {
if
(!
$this
->initated) {
$this
->_init_db();// 初始化數據庫
$this
->_init_setting();//系統設置初始化
$this
->_init_user();//用戶信息初始化
$this
->_init_session();// session操做初始化
$this
->_init_mobile();//手機功能初始化
$this
->_init_cron();//計劃任務初始化
$this
->_init_misc();//其餘功能初始化
}
$this
->initated = true;//設置完成標誌
}
|
核心代碼第一句 $this->_init_db();
1
2
3
4
5
6
7
8
9
|
private
function
_init_db() {
if
(
$this
->init_db) {
$driver
=
'db_driver_mysql'
;
if
(getglobal(
'config/db/slave'
)) {//在設置裏修改slave能夠修改數據庫驅動類,默認爲db_dirver_mysql
$driver
=
'db_driver_mysql_slave'
;
}
DB::init(
$driver
,
$this
->config[
'db'
]);//DB類位於:./source/class/discuz/discuz_database.php
}
}
|
DB::init方法是在discuz_database類中實例化了數據庫驅動類db_driver_mysql驅動類,並將其賦值給DB::db屬性,根據自動引入規則驅動類的位置在:./source/class/db/db_driver_mysql.php;
核心代碼第二句 $this->_init_setting(),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
private
function
_init_setting() {
if
(
$this
->init_setting) {
if
(
empty
(
$this
->
var
[
'setting'
])) {
$this
->cachelist[] =
'setting'
;
}
if
(
empty
(
$this
->
var
[
'style'
])) {
$this
->cachelist[] =
'style_default'
;
}
if
(!isset(
$this
->
var
[
'cache'
][
'cronnextrun'
])) {
$this
->cachelist[] =
'cronnextrun'
;
}
}
!
empty
(
$this
->cachelist) && loadcache(
$this
->cachelist);//主要是這句,加載緩存,實現的過程能夠看function_core.php中的第687-716行,實際是把緩存賦值給$_G變量($_G['setting'],$_G['cache'],$_G['grouplevels']),處理緩存的實際上是在第700行 C::t('common_syscache')->fetch_all($caches);,這塊是重點。能夠研究一下,DZ的緩存部分,這裏我略講一下,用C::t('common_syscache')->fetch_all($caches) 實例化了一個對象common_syscache 位置:./source/class/table/table_common_syscache.php,挺繞得,我看了半天代碼才找出來,其實這個完整的對象是discuz_container。common_syscache對象只是discuz_container的一個屬性obj;在class_core.php的第76-90行能夠看出這種關係來,table_common_syscache.php第38行,$data = memory('get', $cachenames);這個是最後獲得的緩存數據,咱們來追下memory函數,第一個參數是get,那麼會執行function_core.php中的第1687行 case 'get': return C::memory()->get($key, $value); 其中C::memory()是實例化了discuz_memory對象,在./source/class/discuz/discuz_memory.php ;看get方法在第70-102行,它有兩個參數,get($key, $prefix = '')。get方法第97行$ret = $this->memory->get($this->_key($key));使用了memory_driver_eaccelerator類的get方法,位置./source/class/memory/memory_driver_eaccelerator.php第22行,return eaccelerator_get($key);,緩存就是依靠eaccelerator_get函數獲取的
if
(!
is_array
(
$this
->
var
[
'setting'
])) {
$this
->
var
[
'setting'
] =
array
();
}
}
|
核心代碼第三句$this->_init_user();discuz_application.php 428-493行
$auth = getglobal('auth', 'cookie') 獲得cookie中的auth的值,加密過的值
$auth = daddslashes(explode("\t", authcode($auth, 'DECODE'))); 利用authcode函數解密,獲得一個數組
list($discuz_pw, $discuz_uid) = empty($auth) || count($auth) < 2 ? array('', '') : $auth; 從這句看數組第一個元素爲密碼,第二個元素是會員登錄的ID。存在common_member表中。
$user = getuserbyuid($discuz_uid, 1);利用getuserbyuid獲得會員信息,第二個參數若是是1而且在common_member中沒有該會員就去common_member_archive表中去尋找,不然直接去common_member表中查找
1
2
3
4
5
6
7
8
9
|
if
(!
empty
(
$user
) &&
$user
[
'password'
] ==
$discuz_pw
) {若是查出的密碼是對的
if
(isset(
$user
[
'_inarchive'
])) {
C::t(
'common_member_archive'
)->move_to_master(
$discuz_uid
);若是數組中有_inarchive元素就將當前查到的用戶信息插入到用戶表common_member表中
}
$this
->
var
[
'member'
] =
$user
;將用戶信息壓入模板變量中
}
else
{
$user
=
array
();
$this
->_init_guest();//設置沒登錄的訪客的信息
}
|
1
2
3
|
if
(
$user
&&
$user
[
'groupexpiry'
] > 0 &&
$user
[
'groupexpiry'
] < TIMESTAMP && (getgpc(
'mod'
) !=
'spacecp'
|| CURSCRIPT !=
'home'
)) {
dheader(
'location: home.php?mod=spacecp&ac=usergroup&do=expiry'
);
//若是登錄時間過時了,或者訪問的是home.php下的內容時跳轉到登錄頁面
}
|
這裏做用是檢查登錄了沒有。
462行;!empty($this->cachelist) && loadcache($this->cachelist);裝載緩存, 使用緩存能夠參照我另外一篇文章中關於緩存的應用
477行;$this->var['member']['lastvisit'] = TIMESTAMP - 3600;dsetcookie('lastvisit', TIMESTAMP - 3600, 86400 * 30);設置最後瀏覽的時間
464-490行,設置了cookie、全局變量、增長var屬性變量
核心代碼第四句 $this->_init_session();discuz_application.php 386-426行
設置session類,更新用戶狀態
1
2
3
4
5
|
<?php
$sessionclose
= !
empty
(
$this
->
var
[
'setting'
][
'sessionclose'
]);
//設置中sessionclose是否爲真
$this
->session =
$sessionclose
?
new
discuz_session_close() :
new
discuz_session();
//若是爲真就實例化discuz_session_close類 應該是關閉session後的解決方案,不然實例化discuz_session類,位置在source/class/discuz/discuz_session.php
if($this->session->get('groupid') == 6)判斷session中的groupid合法性 $this->session->set('lastactivity', TIMESTAMP);設置最後訪問時間爲當前時間 dsetcookie('lip', $this->var['member']['lastip'].','.$this->var['member']['lastvisit']);第一次訪問的話設置訪問IP的session C::t('common_member_status')->update($this->var['uid'], array('lastip' => $this->var['clientip'], 'lastvisit' => TIMESTAMP));//更新用戶的狀態 ?>
|
核心代碼第五句 $this->_init_mobile();discuz_application.php 680-789行
大概看了下,都是設置手機訪問的一些變量,全局變量,cookie,session,跳轉,常量等,有空細看下
核心代碼第六句$this->_init_cron();discuz_application.php 508-515行
計劃任務初始化 。配置文件中 $_config['remote']['cron'] = 1;設置後;遠程調用: 開啓外部 cron 任務. 系統內部再也不執行cron, cron任務由外部程序激活
1
2
3
4
5
6
|
$ext
=
empty
(
$this
->config[
'remote'
][
'on'
]) ||
empty
(
$this
->config[
'remote'
][
'cron'
]) || APPTYPEID == 200;
if
(
$this
->init_cron &&
$this
->init_setting &&
$ext
) {
//若是遠程調用: 開啓外部 cron 任務後調用discuz_cron::run();類
if
(
$this
->
var
[
'cache'
][
'cronnextrun'
] <= TIMESTAMP) {
discuz_cron::run();
}
}
|
至此咱們看到了一個完整的初始化過程
1
2
3
4
5
6
7
|
require_once
'./source/class/class_core.php'
;
//引入核心類文件,做用爲:自動引入類規則,錯誤和異常處理,單例建立discuz_application類實例,引入默認函數庫function.core.php
require_once
'./source/function/function_home.php'
;
//項目函數庫
$discuz
= C::app();
//實例化desiuz_application類
$cachelist
=
array
(
'magic'
,
'userapp'
,
'usergroups'
,
'diytemplatenamehome'
);
$discuz
->cachelist =
$cachelist
;
//設置緩存列表
$discuz
->init();
//初始化整個應用
|