開啟admin.php
define('IN_ADMINCP', TRUE);
//定義常量IN_ADMINCP為true 這樣在後面的每個頁面都會判斷
if(!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
exit('Access Denied');
}
//防止外面直接訪問後臺檔案,必須通過admin.php包含才可以訪問其他檔案,IN_DISCUZ在/sorce/class/class_core.php裡定義的常量,後面幾行馬上包含該檔案
define('NOROBOT', TRUE);
//定義常量NOROBOT為true,用於阻止搜尋引擎爬蟲抓取。
define('ADMINSCRIPT', basename(__FILE__));//admin.php
//__FILE__是獲取檔案磁碟位置詳細路徑,比如:D:\DedeAMPZ\web2013\discuz_video\upload\admin.php
//basename(__FILE__)就是取檔名 也就是admin.php
define('CURSCRIPT', 'admin');
//定義常量CURSCRIPT為admin,當前指令碼為admin
define('HOOKTYPE', 'hookscript');
//定義常量HOOKTYPE 為 hookscript
define('APPTYPEID', 0);
//定義APPTYPEID 為 0
require './source/class/class_core.php';
包含核心類class_core.php
程式進入class_core.php內
error_reporting(E_ALL);
//定義錯誤報告為E_ALL
define('IN_DISCUZ', true);
//定義常量IN_DISCUZ為true 後續判讀,防止外界直接訪問內部頁面
define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -12));
//定義DISCUZ_ROOT為DISCUZ的根目錄也就是upload目錄的磁碟位置,這個常量後續會很常用到
define('DISCUZ_CORE_DEBUG', false);
//定義除錯模式為 false後續可以修改為true進行除錯
define('DISCUZ_TABLE_EXTENDABLE', TRUE);
//定義常量'DISCUZ_TABLE_EXTENDABLE' 為true
set_exception_handler(array('core', 'handleException'));
//PHP自帶函式 使用 core::handleException 來執行異常處理可以是單個函式名為引數,也可以是類和函式組成的陣列
if(DISCUZ_CORE_DEBUG) {
set_error_handler(array('core', 'handleError'));//設定錯誤處理函式 core::handleError 來執行
register_shutdown_function(array('core', 'handleShutdown'));//致命錯誤處理函式 core::handleShutdown 來執行
}
//如果是除錯模式的話設定錯誤處理函式為core::handleError,設定致命錯誤處理函式為core::handleShutdown
if(function_exists('spl_autoload_register')) {
spl_autoload_register(array('core', 'autoload'));
} else {
function __autoload($class) {
return core::autoload($class);
}
}
//自動載入類,執行 以下autoload函式 PHP5之後如果試圖呼叫沒有載入的類就會自動呼叫__autoload()函式或者執行spl_autoload_register()指定的函式
//直接呼叫類時會先呼叫core::autoload($class)函式,在這個函式裡會包含該類檔案
C::creatapp();
//執行C::createapp()函式,雙冒號是呼叫類的靜態函式。DISCUZ裡大多都用的是靜態函式
在類名的最下方有C的定義
class C extends core {}
class DB extends discuz_database {}
類名C是繼承於core的,執行C::createapp()就是執行core::createapp()
再看core::createapp()函式如下:
public static function creatapp() {
if(!is_object(self::$_app)) {
//discuz_application主要定義了mem session misic mobile setting等陣列
//在這裡直接呼叫discuz_application類,會觸發core::autoload('discuz_application')執行,因為spl_autoload_register()函式設定了
self::$_app = discuz_application::instance();//由於執行了spl_autoload_register自動載入類
//instance執行了$object = new self();這樣就執行了__construct函式
}
return self::$_app;
}
該函式直接返回core::$_app , core::$_app 開始為空,所以呼叫discuz_application::instance();
由於上面設定了類自動載入,所以呼叫discuz_application的時候,會先呼叫
core::autoload()函式,
函式執行到 core::autoload()裡,程式碼如下:
//自動載入類
public static function autoload($class) {
$class = strtolower($class);//變為小寫
if(strpos($class, '_') !== false) {
list($folder) = explode('_', $class);
$file = 'class/'.$folder.'/'.substr($class, strlen($folder) + 1);
} else {
$file = 'class/'.$class;
}
try {
self::import($file);
return true;
} catch (Exception $exc) {
$trace = $exc->getTrace();
foreach ($trace as $log) {
if(empty($log['class']) && $log['function'] == 'class_exists') {
return false;
}
}
discuz_error::exception_error($exc);
}
}
//此時傳遞給autoload的變數$class是discuz_application,由於檔名中含有_,所以$file是class/discuz/discuz_application.php,如果沒有_的類,則在class/類名.php,然後執行
self::import($file);
函式進入core::import()內程式碼如下:
public static function import($name, $folder = '', $force = true) {
$key = $folder.$name;
if(!isset(self::$_imports[$key])) {
$path = DISCUZ_ROOT.'/source/'.$folder;
if(strpos($name, '/') !== false) {
$pre = basename(dirname($name));
$filename = dirname($name).'/'.$pre.'_'.basename($name).'.php';
} else {
$filename = $name.'.php';
}
if(is_file($path.'/'.$filename)) {
self::$_imports[$key] = true;
$rt = include $path.'/'.$filename;
return $rt;
} elseif(!$force) {
return false;
} else {
throw new Exception('Oops! System file lost: '.$filename);
}
}
return true;
}
//此時傳遞給core::import()的引數為class/discuz/discuz_application.php,第2,3個引數為預設的
$key = $folder.$name;
if(!isset(self::$_imports[$key])) {
如果包含了檔案則不重複包含,包含過後都會把類名儲存在$_imports[]陣列內,所以開始判斷下這個鍵值是否已經存在,不存在執行下一步,然後下面的程式碼也就是包含對應的PHP檔案了,不詳細多說。
包含了檔案後,程式繼續執行,因為此時discuz_application已經包含進來,可以繼續執行以下函式。
self::$_app = discuz_application::instance();
執行discuz_application::instance()函式
----------------------------------------程式即將跳轉----------------------------------------
static function &instance() {
static $object;
if(empty($object)) {
$object = new self();//初始化一個類,如此便開始執行__construct()函式
}
return $object;
}
初始化一個類,$object=new self(),初始化後必然執行__construct()函式
----------------------------------------程式即將跳轉----------------------------------------
程式碼如下
public function __construct() {
$this->_init_env();//環境設定
$this->_init_config();//配置
$this->_init_input();//設定GET,POST ,COOKIE
$this->_init_output();//rss charset GZIP等。
}
----------------------------------------程式即將跳轉----------------------------------------
$this->_init_env();//環境設定
程式碼如下:
private function _init_env() {
error_reporting(E_ERROR);
if(PHP_VERSION < '5.3.0') {
set_magic_quotes_runtime(0);
}
define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
define('ICONV_ENABLE', function_exists('iconv'));
define('MB_ENABLE', function_exists('mb_convert_encoding'));
define('EXT_OBGZIP', function_exists('ob_gzhandler'));
define('TIMESTAMP', time());//記錄開始時間,沒重新整理頁面都會執行
$this->timezone_set();//設定時區
//包含核心函式庫
if(!defined('DISCUZ_CORE_FUNCTION') && !@include(DISCUZ_ROOT.'./source/function/function_core.php')) {
exit('function_core.php is missing');
}
//記憶體設定為128M
if(function_exists('ini_get')) {
$memorylimit = @ini_get('memory_limit');
if($memorylimit && return_bytes($memorylimit) < 33554432 && function_exists('ini_set')) {
ini_set('memory_limit', '128m');
}
}
define('IS_ROBOT', checkrobot());
//$GLOBALS為全域性變數陣列,比如外部定義了$f00="123",在這裡通過$GLOBALS['foo']='123';
foreach ($GLOBALS as $key => $value) {
if (!isset($this->superglobal[$key])) {
$GLOBALS[$key] = null; unset($GLOBALS[$key]);//不明白為何要清空$GLOBALS,似乎是用自己的一套變數清空系統變數
}
}
global $_G;//超級大陣列
$_G = array(
'uid' => 0,
'username' => '',
'adminid' => 0,
'groupid' => 1,
'sid' => '',
'formhash' => '',
'connectguest' => 0,
'timestamp' => TIMESTAMP,
'starttime' => microtime(true),
'clientip' => $this->_get_client_ip(),//獲取客戶端IP地址
'referer' => '',
'charset' => '',
'gzipcompress' => '',
'authkey' => '',
'timenow' => array(),
'widthauto' => 0,
'disabledwidthauto' => 0,
'PHP_SELF' => '',
'siteurl' => '',
'siteroot' => '',
'siteport' => '',
'pluginrunlist' => !defined('PLUGINRUNLIST') ? array() : explode(',', PLUGINRUNLIST),
'config' => array(),
'setting' => array(),
'member' => array(),
'group' => array(),
'cookie' => array(),
'style' => array(),
'cache' => array(),
'session' => array(),
'lang' => array(),
'my_app' => array(),
'my_userapp' => array(),
'fid' => 0,
'tid' => 0,
'forum' => array(),
'thread' => array(),
'rssauth' => '',
'home' => array(),
'space' => array(),
'block' => array(),
'article' => array(),
'action' => array(
'action' => APPTYPEID,
'fid' => 0,
'tid' => 0,
),
'mobile' => '',
'notice_structure' => array(
'mypost' => array('post','pcomment','activity','reward','goods','at'),
'interactive' => array('poke','friend','wall','comment','click','sharenotice'),
'system' => array('system','myapp','credit','group','verify','magic','task','show','group','pusearticle','mod_member','blog','article'),
'manage' => array('mod_member','report','pmreport'),
'app' => array(),
),
'mobiletpl' => array('1' => 'mobile', '2' => 'touch', '3' => 'wml','yes' => 'mobile'),
);
//dhtmlspecialchars 在function_core.php裡
$_G['PHP_SELF'] = dhtmlspecialchars($this->_get_script_url());
$_G['basescript'] = CURSCRIPT;//在執行首個PHP檔案裡定義了,比如member.php裡定義了member
$_G['basefilename'] = basename($_G['PHP_SELF']);
$sitepath = substr($_G['PHP_SELF'], 0, strrpos($_G['PHP_SELF'], '/'));
if(defined('IN_API')) {
$sitepath = preg_replace("/\/api\/?.*?$/i", '', $sitepath);
} elseif(defined('IN_ARCHIVER')) {
$sitepath = preg_replace("/\/archiver/i", '', $sitepath);
}
$_G['isHTTPS'] = ($_SERVER['HTTPS'] && strtolower($_SERVER['HTTPS']) != 'off') ? true : false;
$_G['siteurl'] = dhtmlspecialchars('http'.($_G['isHTTPS'] ? 's' : '').'://'.$_SERVER['HTTP_HOST'].$sitepath.'/');
$url = parse_url($_G['siteurl']);
$_G['siteroot'] = isset($url['path']) ? $url['path'] : '';
$_G['siteport'] = empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' || $_SERVER['SERVER_PORT'] == '443' ? '' : ':'.$_SERVER['SERVER_PORT'];
if(defined('SUB_DIR')) {
$_G['siteurl'] = str_replace(SUB_DIR, '/', $_G['siteurl']);
$_G['siteroot'] = str_replace(SUB_DIR, '/', $_G['siteroot']);
}
$this->var = & $_G;
}
----------------------------------------程式即將跳轉----------------------------------------
$this->_init_env();//環境設定
$this->_init_config();//配置
$this->_init_input();//設定GET,POST ,COOKIE
$this->_init_output();//rss charset GZIP等。