ThinkPHP 源码分析(二):运行应用

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 框架执行流程走到了终点。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,853评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,930评论 25 708
  • 可以查看我做的简易流程图。 也可以看官方的标准答案。 用户URL请求 调用应用入口文件(通常是网站的index.p...
    苏近之2017阅读 794评论 0 3
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,201评论 30 471
  • 最近朋友开了一个书法班,在迪拜。 话说迪拜是一个很聒躁的地方。近年来华人舞了宝剑,挥了扇子,蹲了马步,绣了旗袍,总...
    沙漠花海阅读 311评论 0 1