tp 框架在加载完各种文件,做好准备之后,才开始要肩负起运行应用的重任。在 Think\Think::start() 方法的最后,App::run() 方法登场。
/**
* 应用程序初始化
* @access public
* @return void
*/
static public function init() {
// 加载动态应用公共文件和配置
load_ext_file(COMMON_PATH);
// 日志目录转换为绝对路径 默认情况下存储到公共模块下面
C('LOG_PATH', realpath(LOG_PATH).'/Common/');
// 定义当前请求的系统常量
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调度
Dispatcher::dispatch();
if(C('REQUEST_VARS_FILTER')){
// 全局安全过滤
// 对数组中的每个成员递归地应用用户函数
array_walk_recursive($_GET, 'think_filter');
array_walk_recursive($_POST, 'think_filter');
array_walk_recursive($_REQUEST, 'think_filter');
}
// URL调度结束标签
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() 中最重要的是两句代码,这两句分别执行了该类中的 init 和 exec 方法。在这两个方法执行的前后,还有三个钩子被监听,这三个钩子分别 app_init、app_begin、app_end。
init 方法是 App 类中的应用程序初始化方法,它将完成 Think\Think::start() 未完成的部分初始化工作。剩下的初始化工作的重点是解析请求的 URL,在解析 URL 时,先是定义当前请求的系统常量,然后调用了 Dispatcher::dispatch() 方法,Dispatcher 类是 tp 框架中负责完成 URL 解析、路由和调度的类,这里调用的 dispatch 方法的作用是将 URL映射到控制器,也就是从 URL 中解析出对应的模型、控制器和操作。这样 tp 框架就知道它该调用哪个模型,哪个控制器,以及哪个操作了。
/**
* 应用程序初始化
* @access public
* @return void
*/
static public function init() {
// 加载动态应用公共文件和配置
load_ext_file(COMMON_PATH);
// 日志目录转换为绝对路径 默认情况下存储到公共模块下面
C('LOG_PATH', realpath(LOG_PATH).'/Common/');
// 定义当前请求的系统常量
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调度
Dispatcher::dispatch();
if(C('REQUEST_VARS_FILTER')){
// 全局安全过滤
// 对数组中的每个成员递归地应用用户函数
array_walk_recursive($_GET, 'think_filter');
array_walk_recursive($_POST, 'think_filter');
array_walk_recursive($_REQUEST, 'think_filter');
}
// URL调度结束标签
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 方法运行完后,exec 方法开始负责执行应用程序。首先它会创建控制器实例,并获得当前操作名。之后调用 invokeAction 方法,此方法将执行控制器实例中相应的操作。
try{
self::invokeAction($module,$action);
} catch (\ReflectionException $e) {
// 方法调用发生异常后 引导到__call方法处理
$method = new \ReflectionMethod($module,'__call');
$method->invokeArgs($module,array($action,''));
}
在 invokeAction 方法中,使用到了 PHP 的两个反射类,ReflectionClass 和 ReflectionMethod。这两个类可以让我们动态的得到类和方法的信息,以及动态调用对象的方法。借助于这两个类,我们可以检测,即将执行的控制器实例中的操作,其访问控制是否为 public,以及是否是类方法。
至此,一次完整的 tp 框架执行流程走到了终点。
网友评论