tp 框架在加載完各種文件耗拓,做好準(zhǔn)備之后拇颅,才開始要肩負(fù)起運(yùn)行應(yīng)用的重任。在 Think\Think::start() 方法的最后乔询,App::run() 方法登場樟插。
/**
* 應(yīng)用程序初始化
* @access public
* @return void
*/
static public function init() {
// 加載動態(tài)應(yīng)用公共文件和配置
load_ext_file(COMMON_PATH);
// 日志目錄轉(zhuǎn)換為絕對路徑 默認(rèn)情況下存儲到公共模塊下面
C('LOG_PATH', realpath(LOG_PATH).'/Common/');
// 定義當(dāng)前請求的系統(tǒng)常量
define('NOW_TIME', $_SERVER['REQUEST_TIME']);
define('REQUEST_METHOD',$_SERVER['REQUEST_METHOD']);
define('IS_GET', REQUEST_METHOD =='GET' ? true : false);
define('IS_POST', REQUEST_METHOD =='POST' ? true : false);
define('IS_PUT', REQUEST_METHOD =='PUT' ? true : false);
define('IS_DELETE', REQUEST_METHOD =='DELETE' ? true : false);
// URL調(diào)度
Dispatcher::dispatch();
if(C('REQUEST_VARS_FILTER')){
// 全局安全過濾
// 對數(shù)組中的每個成員遞歸地應(yīng)用用戶函數(shù)
array_walk_recursive($_GET, 'think_filter');
array_walk_recursive($_POST, 'think_filter');
array_walk_recursive($_REQUEST, 'think_filter');
}
// URL調(diào)度結(jié)束標(biāo)簽
Hook::listen('url_dispatch');
define('IS_AJAX', ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || !empty($_POST[C('VAR_AJAX_SUBMIT')]) || !empty($_GET[C('VAR_AJAX_SUBMIT')])) ? true : false);
// TMPL_EXCEPTION_FILE 改為絕對地址
C('TMPL_EXCEPTION_FILE',realpath(C('TMPL_EXCEPTION_FILE')));
return ;
}
App::run() 中最重要的是兩句代碼,這兩句分別執(zhí)行了該類中的 init 和 exec 方法竿刁。在這兩個方法執(zhí)行的前后黄锤,還有三個鉤子被監(jiān)聽,這三個鉤子分別 app_init食拜、app_begin鸵熟、app_end。
init 方法是 App 類中的應(yīng)用程序初始化方法负甸,它將完成 Think\Think::start() 未完成的部分初始化工作流强。剩下的初始化工作的重點是解析請求的 URL,在解析 URL 時呻待,先是定義當(dāng)前請求的系統(tǒng)常量打月,然后調(diào)用了 Dispatcher::dispatch() 方法,Dispatcher 類是 tp 框架中負(fù)責(zé)完成 URL 解析蚕捉、路由和調(diào)度的類僵控,這里調(diào)用的 dispatch 方法的作用是將 URL映射到控制器,也就是從 URL 中解析出對應(yīng)的模型鱼冀、控制器和操作报破。這樣 tp 框架就知道它該調(diào)用哪個模型,哪個控制器千绪,以及哪個操作了充易。
/**
* 應(yīng)用程序初始化
* @access public
* @return void
*/
static public function init() {
// 加載動態(tài)應(yīng)用公共文件和配置
load_ext_file(COMMON_PATH);
// 日志目錄轉(zhuǎn)換為絕對路徑 默認(rèn)情況下存儲到公共模塊下面
C('LOG_PATH', realpath(LOG_PATH).'/Common/');
// 定義當(dāng)前請求的系統(tǒng)常量
define('NOW_TIME', $_SERVER['REQUEST_TIME']);
define('REQUEST_METHOD',$_SERVER['REQUEST_METHOD']);
define('IS_GET', REQUEST_METHOD =='GET' ? true : false);
define('IS_POST', REQUEST_METHOD =='POST' ? true : false);
define('IS_PUT', REQUEST_METHOD =='PUT' ? true : false);
define('IS_DELETE', REQUEST_METHOD =='DELETE' ? true : false);
// URL調(diào)度
Dispatcher::dispatch();
if(C('REQUEST_VARS_FILTER')){
// 全局安全過濾
// 對數(shù)組中的每個成員遞歸地應(yīng)用用戶函數(shù)
array_walk_recursive($_GET, 'think_filter');
array_walk_recursive($_POST, 'think_filter');
array_walk_recursive($_REQUEST, 'think_filter');
}
// URL調(diào)度結(jié)束標(biāo)簽
Hook::listen('url_dispatch');
define('IS_AJAX', ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || !empty($_POST[C('VAR_AJAX_SUBMIT')]) || !empty($_GET[C('VAR_AJAX_SUBMIT')])) ? true : false);
// TMPL_EXCEPTION_FILE 改為絕對地址
C('TMPL_EXCEPTION_FILE',realpath(C('TMPL_EXCEPTION_FILE')));
return ;
}
init 方法運(yùn)行完后,exec 方法開始負(fù)責(zé)執(zhí)行應(yīng)用程序荸型。首先它會創(chuàng)建控制器實例盹靴,并獲得當(dāng)前操作名。之后調(diào)用 invokeAction 方法,此方法將執(zhí)行控制器實例中相應(yīng)的操作稿静。
try{
self::invokeAction($module,$action);
} catch (\ReflectionException $e) {
// 方法調(diào)用發(fā)生異常后 引導(dǎo)到__call方法處理
$method = new \ReflectionMethod($module,'__call');
$method->invokeArgs($module,array($action,''));
}
在 invokeAction 方法中梭冠,使用到了 PHP 的兩個反射類,ReflectionClass 和 ReflectionMethod改备。這兩個類可以讓我們動態(tài)的得到類和方法的信息控漠,以及動態(tài)調(diào)用對象的方法。借助于這兩個類悬钳,我們可以檢測盐捷,即將執(zhí)行的控制器實例中的操作,其訪問控制是否為 public默勾,以及是否是類方法碉渡。
至此,一次完整的 tp 框架執(zhí)行流程走到了終點母剥。