前言:
由于比较懒散,但是又是有点强迫症,所以还是想继续把ThinkPHP3.2的加载过程这个烂尾楼补充完整。
========================================分割线=================================
上次最后一个篇说道加载APP:run() ----在ThinkPHP/Library/Think/Thinkclass.php下
在这里说明一下APP在什么时候会被定义并且加载的
配置文件ThinkPHP/Mode/common.php在ThinkPHP/Library/Think/Thinkclass.php 被引入的时候,APP这个class被同时引入
// 函数和类文件
// 函数和类文件 ‘core‘ => array( THINK_PATH.‘Common/functions.php‘, COMMON_PATH.‘Common/function.php‘, CORE_PATH . ‘Hook‘.EXT, CORE_PATH . ‘App‘.EXT, CORE_PATH . ‘Dispatcher‘.EXT, //CORE_PATH . ‘Log‘.EXT, CORE_PATH . ‘Route‘.EXT, CORE_PATH . ‘Controller‘.EXT, CORE_PATH . ‘View‘.EXT, BEHAVIOR_PATH . ‘BuildLiteBehavior‘.EXT, BEHAVIOR_PATH . ‘ParseTemplateBehavior‘.EXT, BEHAVIOR_PATH . ‘ContentReplaceBehavior‘.EXT, ),
因此我们知道APP的class文件地址为ThinkPHP/Library/Think/App.class.php,并且执行下的run方法
/** * 运行应用实例 入口文件使用的快捷方法 * @access public * @return void */ static public function run() { // 应用初始化标签 Hook::listen(‘app_init‘); App::init(); // 应用开始标签 Hook::listen(‘app_begin‘); // Session初始化 if(!IS_CLI){ session(C(‘SESSION_OPTIONS‘)); } // 记录应用初始化时间 G(‘initTime‘); App::exec(); // 应用结束标签 Hook::listen(‘app_end‘); return ; }
对run方法下的代码进行分析
第一段:
// 应用初始化标签 Hook::listen(‘app_init‘);
Hook这THINKPHP叫系统钩子(应该是想钓鱼一样,用这个把鱼勾上来把)
引入的时间:应该他是包含在commom.php这个core数组中被引入
文件位置:ThinPHP/Library/Think/Hook.class.php
第一行:Hook::listen(‘app_init‘);
简化代码:
/** * 监听标签的插件 * @param string $tag 标签名称 * @param mixed $params 传入参数 * @return void */ static public function listen($tag, &$params=NULL) { if(isset(self::$tags[$tag])) { foreach (self::$tags[$tag] as $name) { $result = self::exec($name, $tag,$params); if(false === $result) { // 如果返回false 则中断插件执行 return ; } } } return; }
其中self::exec()代码在下面
/** * 执行某个插件 * @param string $name 插件名称 * @param string $tag 方法名(标签名) * @param Mixed $params 传入的参数 * @return void */ static public function exec($name, $tag,&$params=NULL) { if(‘Behavior‘ == substr($name,-8) ){ // 行为扩展必须用run入口方法 $tag = ‘run‘; } $addon = new $name(); return $addon->$tag($params); }
关于参数app_init在什么时候被传入 定义到了self::$tags()下做简单说明
配置的文件同样是在ThinkPHP/Mode/common.php下的tags数组
通过ThinkPHP/Library/Think/Thinkclass.php
// 加载模式行为定义 if(isset($mode[‘tags‘])) { Hook::import(is_array($mode[‘tags‘])?$mode[‘tags‘]:include $mode[‘tags‘]); }
配置到系统钩子的tags中
通过配置文件我们看到app_init对于的类是BuildLiteBehavior
第一段代码总结:
实例化BuildLiteBehavior类该类地址ThinkPHP/Library/bechavior/BuildLiteBeavior.class.php 并且运行其中的run方法
关于BuildLiteBeavior.class.php里面大致的代码 是把之前运行的代码 把之前运行的代码都整理到一起,包括其中的参数的定义等,默认情况下该功能是关闭状态,所以不需要理会
第二段
App::init();
集体代码:
/** * 应用程序初始化 * @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 ; }
这里大致的内容,通过URL获取其中的模块名:控制器名:方法名
第三段:
// 应用开始标签 Hook::listen(‘app_begin‘);
更具之前的经验,app_begin的文件是在ThinkPHP/library/Behavior/ReadHtmlCacheBehavior.php
并且运行这个文件的run方法
Run方法代码
// 行为扩展的执行入口必须是run public function run(&$params){ // 开启静态缓存 if(IS_GET && C(‘HTML_CACHE_ON‘)) { $cacheTime = $this->requireHtmlCache(); if( false !== $cacheTime && $this->checkHTMLCache(HTML_FILE_NAME,$cacheTime)) { //静态页面有效 // 读取静态页面输出 echo Storage::read(HTML_FILE_NAME,‘html‘); exit(); } } }
如果定义了缓存文件规则 则使用缓存文件,由于默认情况下是关闭
第三部分:
// Session初始化 if(!IS_CLI){ session(C(‘SESSION_OPTIONS‘)); } // 记录应用初始化时间 G(‘initTime‘);
如果是一个来自网页的请求,则利用配置文件中的SESSION_OPTIONS规则对session进行初始化。
记录初始化时间
第四部分:
App::exec();
具体代码在/ThinkPHP/Library/Think/App.class.php文件下的exec()
这个方法和基本功能是实现让框架找到对应的控制器和方法。
关于路由和App::exec();方法,下次分开具体说明
总结:
/** * 运行应用实例 入口文件使用的快捷方法 * @access public * @return void */ static public function run() { // 应用初始化标签 Hook::listen(‘app_init‘); //默认情况下无效 App::init(); //通过URL 将模块名 控制器名 和方法名找到 // 应用开始标签 Hook::listen(‘app_begin‘); //静态缓存页面 ,默认关闭 // Session初始化 if(!IS_CLI){ session(C(‘SESSION_OPTIONS‘)); //根据配置文件中的SESSION_OPTIONS进行session初始化 } // 记录应用初始化时间 G(‘initTime‘); //做记录 App::exec(); //知道对于的控制器和方法名 并运行 // 应用结束标签 Hook::listen(‘app_end‘);//默认关闭 该功能是显示网页请求的一些sql执行,响应时间等参数 return ; }