ThinkPHP3.2 加载过程(四)
前言:
由于比较懒散,但是又是有点强迫症,所以还是想继续把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 ;
}
ThinkPHP3.2 加载过程(四)的更多相关文章
- ThinkPHP3.2 加载过程(一)
加载过程(官方介绍) : 用户URL请求 调用应用入口文件(通常是网站的index.php) 载入框架入口文件(ThinkPHP.php) 记录初始运行时间和内存开销 系统常量判断及定义 载入框架引导 ...
- ThinkPHP3.2 加载过程(二)
回顾: 上次介绍了 ThinkPHP 的 Index.PHP入口文件.但只是TP的入口前面的入口(刷boss总是要过好几关才能让你看到 ,不然boss都没面子啊),从Index.PHP最后一行把我们引 ...
- ThinkPHP3.2 加载过程(三)
上次回顾: IS_CGI ,IS_WIN,IS_CLI,MAGIC_QUOTES_GPC干嘛用 IS_WIN 看了一下后面的代码 基本上就是为了保证在不同环境下运行时,由于有些操作系统会对文件路径大 ...
- 工厂模式模拟Spring的bean加载过程
一.前言 在日常的开发过程,经常使用或碰到的设计模式有代理.工厂.单例.反射模式等等.下面就对工厂模式模拟spring的bean加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂 ...
- linux内核启动以及文件系统的加载过程
Linux 内核启动及文件系统加载过程 当u-boot 开始执行 bootcmd 命令,就进入 Linux 内核启动阶段.普通 Linux 内核的启动过程也可以分为两个阶段.本文以项目中使用的 lin ...
- 你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)
前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程, ...
- JVM——类的加载过程
附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...
- UIViewController加载过程
UIViewController是视图和数据的桥梁,UIViewController是所有controller的基类,ios内置了很多试图控制器,如导航控制器,tableViewController等 ...
- Java 类的加载过程(阿里面试题)
问以下程序打印出什么内容: 问题及解析如下: /** * 加载方法不等于执行方法,初始化变量则会赋值 * 类加载顺序应为 加载静态方法-初始化静态变量-执行静态代码块 * 实例化时 先加载非静态方法- ...
随机推荐
- ABAP DEBUG
[Function] Command=/H Type=SystemCommand 将上面的文件推动到SAP 窗口 可以启动调试 ------------------------------------ ...
- iOS 时间戳转换为时间
NSString *str=";//时间戳 NSTimeInterval time=[str doubleValue]+;//因为时差问题要加8小时 == 28800 sec NSDate ...
- 采用Reflector的VS.net插件断点调试无源码DLL 分类:
.Net的编程利器Reflector可以反编译基于.net开发的应用程序和DLL,其功能强大不用多说.今天想试验一把利用VS.net的插件断点调试外部无源码的DLL(只要是程序集都可以,所以exe也行 ...
- php join函数使用,很是方便
以前数组转换成用逗号隔开的字符串都是自己写一个数组,最后还要去除多余的一个逗号,好麻烦. 无意中发现join函数,原来一句话就可以了. $_array = array('a','b','c','d', ...
- 较具体的介绍JNI
JNI事实上是Java Native Interface的简称,也就是java本地接口.它提供了若干的API实现了和Java和其它语言的通信(主要是C&C++).或许不少人认为Java已经足够 ...
- android学习日记03--常用控件button/imagebutton
常用控件 控件是对数据和方法的封装.控件可以有自己的属性和方法.属性是控件数据的简单访问者.方法则是控件的一些简单而可见的功能.所有控件都是继承View类 介绍android原生提供几种常用的控件bu ...
- [Embed(source="asset.swf")] 使用其中的所有资源
在AS3中,我们可以使用 [Embed(source="asset.swf", symbol="symbol")] private var symbolClas ...
- (原)C++解析XML生成类对象_v1.0 函数指针
要写一个xml解析,解析后获得到的数据变成各个类的对象. 解析有现成的库,使用tinyxml,但是解析出来的类库如何变成各个类的对象, 例如一下这个xml, <musics> <mu ...
- 多线程GCD
经常使用:规避很多线程相关的复杂的逻辑 为什么会gcd?因为pthread和nsthread要求开发人员对线程相关的知识了解深入; 手动启动线程:加锁/解锁;造成很多隐患 --> 苹果公司给出了 ...
- 多线程NSOperation
NSOperation(经常使用): 1.为什么会有NSOperation?弥补gcd的一些问题:1)下载为例子:如果gcd放到队列中的block操作面对网络有问题,block之外无法取消bloc ...