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 ;
    }
时间: 2024-10-13 18:26:15

ThinkPHP3.2 加载过程(四)的相关文章

ThinkPHP3.2 加载过程(二)

原文:ThinkPHP3.2 加载过程(二) 回顾: 上次介绍了 ThinkPHP 的 Index.PHP入口文件.但只是TP的入口前面的入口(刷boss总是要过好几关才能让你看到 ,不然boss都没面子啊),从Index.PHP最后一行把我们引路到了TP的大门前(ThinkPHP/ThinkPHP.php) // 引入ThinkPHP入口文件 require './ThinkPHP/ThinkPHP.php'; 本次目标: 查看TP的大门,同时稍微探索一下大门内部的东西 正文: 先上代码 1

ThinkPHP3.2 加载过程(一)

原文:ThinkPHP3.2 加载过程(一) 加载过程(官方介绍) : 用户URL请求 调用应用入口文件(通常是网站的index.php) 载入框架入口文件(ThinkPHP.php) 记录初始运行时间和内存开销 系统常量判断及定义 载入框架引导类(Think\Think)并执行Think::start方法进行应用初始化 设置错误处理机制和自动加载机制 调用Think\Storage类进行存储初始化(由STORAGE_TYPE常量定义存储类型) 部署模式下如果存在应用编译缓存文件则直接加载(直接

ThinkPHP3.2 加载过程(三)

上次回顾: IS_CGI ,IS_WIN,IS_CLI,MAGIC_QUOTES_GPC干嘛用 IS_WIN 看了一下后面的代码  基本上就是为了保证在不同环境下运行时,由于有些操作系统会对文件路径大小写敏感,定义该参数.对路径进行更严格的检查.  MAGIC_QUOTES_GPC  : 1 if(version_compare(PHP_VERSION,'5.4.0','<')) { 2 ini_set('magic_quotes_runtime',0); 3 define('MAGIC_QUO

java虚拟机学习(四)类的加载过程

类从虚拟机内存加载到从内存卸载,经历的生命周期是:加载,验证,准备,解析,初始化,使用,卸载这几个阶段, 其中验证,解析,初始化被称为 连接过程(Linking). (打算这块和类加载原理后再看class文件结构那篇) 除了解析和使用,其他的过程基本顺序就是这样, 解析可以是在初始化完成之后,这是为了运行时动态绑定. 在虚拟机规范中定义了5中情况(有且只有)必须对类进行初始化(之前进行过,加载,验证,准备): 1.碰到new,getstatic,putstatic,invokestatic这4条

construct2游戏的加载过程

一个Construct 2游戏的加载过程如下: 1. HTML页面和javascript脚本先被下载到本地,这时屏幕无任何显示. 2. 一旦javascript脚本下载完毕,默认的加载界面被显示出来. 3. 游戏的其他部分,主要是游戏中的图片(包括精灵.背景等)在显示默认的加载进度条的同时被下载到本地. 4. 最后,所有的内容下载完毕,准备开始游戏运行. 注意:游戏的声音并不在这四步里被下载到本地,而是在游戏开始后以流的方式导入.所以,在显示加载条的过程中,下载的其实都是图片,包括精灵.背景等等

Linux内核启动及文件系统加载过程

上接博文<u-boot之u-boot-2009.11启动过程分析> 当u-boot开始执行bootcmd命令,就进入Linux内核启动阶段,与u-boot类似,普通Linux内核的启动过程也可以分为两个阶段,但针对压缩了的内核如uImage就要包括内核自解压过程了.本文以项目中使用的linux-2.6.37版源码为例分三个阶段来描述内核启动全过程.第一阶段为内核自解压过程,第二阶段主要工作是设置ARM处理器工作模式.使能MMU.设置一级页表等,而第三阶段则主要为C代码,包括内核初始化的全部工作

你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)

前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程,并且根据加载过程中所遇到的一系列问题提供解决方案. 其实SQL Server作为微软的一款优秀RDBMS,它启动的过程中,本身所带的那些系统库发生问题的情况相对还是很少的,我们在平常使用中,出问题的大部分集中于我们自己建立的用户数据库. 而且,相对于侧重面而言,其实我们更关注的是我们自己建立的用户数

class文件加载过程详解

java类的加载过程. 参考书籍:深入理解JAVA虚拟机 书中错误的地方,p222. 字段解析,在解析一个未解析过的字段时,书中说的是先解析字段表的class_index, 但是,字段表示没有class_index, 跟在字节码指令后边的字段的符号引用是CONSTANT_Field_info. 先对其中的class_index解析. 这个过程,比较复杂,要理解这个过程,你要对Class文件结构比较了解,尤其是字段表. 1.累加载的整体流程 加载--验证--准备--解析--初始化--使用--卸载

JVM类加载机制概述:加载时机与加载过程

摘要: 我们知道,一个.java文件在编译后会形成相应的一个或多个Class文件,这些Class文件中描述了类的各种信息,并且它们最终都需要被加载到虚拟机中才能被运行和使用.事实上,虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型的过程就是虚拟机的类加载机制.本文概述了JVM加载类的时机和生命周期,并结合典型案例重点介绍了类的初始化过程,揭开了JVM类加载机制的神秘面纱. 版权声明: 本文原创作者:书呆子Rico 作者