• CodeIgniter框架——源码分析之CodeIgniter.php


      CodeIgniter.php可以说是CI的核心,大部分MVC的流程都是在这个文件夹中处理的,其中加载了很多外部文件,完成CI的一次完整流程。

      首先是定义了CI的版本(此处为CI 2.2.0),接下来是连续require了2个文件,core/Common.php,config/constants.php,接下来是设置错误处理。

    注:

      源码分析——CI到底做了些什么  

     1 CI的生命周期——system/core/CodeIgniter.php
     2 
     3 include('core/commons.php')
     4 载入 config/constant.php
     5 其他配置
     6 load benchmark,hooks
     7 hook: pre_system
     8 load Config, Utf8, URI, Router, Output
     9 hook: cache_override
    10     - output::_display_cache()
    11 load Security, Input, Lang
    12 hook: pre_controller
    13 $CI = new $class()
    14 hook: post_controller_constructor
    15 hook: post_controller
    16 hook: display_override
    17     - Output::_display()
    18 hook: post_system
    19 清理数据库连接

    源码分析如下:

    <?php  
    /**
     * 详见 http://www.phpddt.com/tag/codeIgniter/
     */
    //如果入口文件系统目录常量BASEPATH没定义,就挂了
    if ( ! defined('BASEPATH')) exit('No direct script access allowed');
            //定义常量:CI_VERSION,CI_CORE
        define('CI_VERSION', '2.2.0');
        define('CI_CORE', FALSE);
     
    /*
     *引入系统目录下core/Common.php,这里面全是CI的系统全局函数如is_php()、load_class()等
     */
        require(BASEPATH.'core/Common.php');
     
    /*
     *加载应用目录下的常量,注意如果存在相应的开发环境目录,则加载对应目录下的文件,ENVIRONMENT实在入口文件定义的
     */
     
        if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
        {
            require(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
        }
        else
        {
            require(APPPATH.'config/constants.php');
        }
     
    /*
     *_exception_handler函数是刚才在Common.php中加载的函数,用来拦截错误,记录日志,
     * set_error_handler是在_exception_handler函数中用load_class加载过来的。
     */
        set_error_handler('_exception_handler');
            //关闭magic quotes,关于这个的详细介绍请看:http://www.phpddt.com/php/php-magic-quotes.html
        if ( ! is_php('5.3'))
        {
            @set_magic_quotes_runtime(0); // Kill magic quotes
        }
     
    /*
     *子类前缀,很重要,也就是说你可以去扩展CI的核心类,后面说,默认配置应该是MY_
     */
            //看看你在index.php中是否定义前缀,没有定义的话就加载配置文件获知,get_config是Common.php中的全局函数
        if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '')
        {
            get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
        }
     
    /*
     *php 程序运行默认是30s,这里用set_time_limt延长了,关于set_time_Limit() http://www.phpddt.com/php/set_time_limit.html
     * 扩展阅读,关于safe_mode:http://www.phpddt.com/php/643.html  ,你会完全明白的
     */
        if (function_exists("set_time_limit") == TRUE AND @ini_get("safe_mode") == 0)
        {
            @set_time_limit(300);
        }
     
    /*
     * 加载Benchmark,它很简单,就是计算任意两点之间程序的运行时间
     */
        $BM =& load_class('Benchmark', 'core');
        $BM->mark('total_execution_time_start');
        $BM->mark('loading_time:_base_classes_start');
     
            //加载钩子,后期会分析到,这玩意特好,扩展它能改变CI的运行流程
        $EXT =& load_class('Hooks', 'core');
     
            //这里就是一个钩子啦,其实就是该钩子程序在这里执行
        $EXT->_call_hook('pre_system');
     
            //加载配置文件,这里面都是一些加载或获取配置信息的函数
        $CFG =& load_class('Config', 'core');
     
        // 如果在index.php中也有配置$assign_to_config,则也把它加入到$CFG
        if (isset($assign_to_config))
        {
            $CFG->_assign_to_config($assign_to_config);
        }
     
            //加载utf8组件、URI组件、Router组件
        $UNI =& load_class('Utf8', 'core');
        $URI =& load_class('URI', 'core');
        $RTR =& load_class('Router', 'core');
        $RTR->_set_routing();
     
        //如果在index.php中定义了$routing,那么就会覆盖上面路由
        if (isset($routing))
        {
            $RTR->_set_overrides($routing);
        }
     
            //加载output输出组件,不然你怎么用$this->Load->view()啊
        $OUT =& load_class('Output', 'core');
     
            //又见钩子,这里你可以自己写钩子程序替代Output类的缓存输出
        if ($EXT->_call_hook('cache_override') === FALSE)
        {
            if ($OUT->_display_cache($CFG, $URI) == TRUE)
            {
                exit;
            }
        }
     
            //安全组件啦,防xss攻击啊,csrf攻击啊
            //关于xss攻击:http://www.phpddt.com/php/php-prevent-xss.html
            //关于csrf:攻击:http://www.phpddt.com/reprint/csrf.html
        $SEC =& load_class('Security', 'core');
     
            //加载输入组件,就是你常用的$this->input->post();等
        $IN    =& load_class('Input', 'core');
     
            //加载语言组件啦
        $LANG =& load_class('Lang', 'core');
     
            //引入CI的控制器父类
        require BASEPATH.'core/Controller.php';
     
        function &get_instance()
        {
            return CI_Controller::get_instance();
        }
     
            //当然你扩展了CI_Controller控制器的话,也要引入啦
        if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
        {
            require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
        }
     
        //加载你自己应用中的控制器Controller,如果没有当然error啦
      //$RTR就是Router类的实例,Router类在构造实例的时候已经对请求的URL进行了解析,并得出对应的类名和方法名,下面就是通过fetch_class方法来获得对应的类名,如果这个控制器的文件存在,就加载这个文件,否则就报错。
    if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php')) { show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'); } include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');   // 好的基础的类都加载完毕了,咱可以mark一下 $BM->mark('loading_time:_base_classes_end');   //路由获取了控制器名和方法名,比如说默认welcome/index $class = $RTR->fetch_class(); $method = $RTR->fetch_method(); //这里CI规定一般非公共的方法以_开头,下面是判断,如果URI不可访问就show_404(),这个404响应的页面也是CI自定义的,show_404()函数可以在Common.php中找到 if ( ! class_exists($class) OR strncmp($method, '_', 1) == 0 OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller'))) ) { if ( ! empty($RTR->routes['404_override'])) { $x = explode('/', $RTR->routes['404_override']); $class = $x[0]; $method = (isset($x[1]) ? $x[1] : 'index'); if ( ! class_exists($class)) { if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) { show_404("{$class}/{$method}"); }   include_once(APPPATH.'controllers/'.$class.'.php'); } } else { show_404("{$class}/{$method}"); } }   //又是钩子,该钩子发生在控制器实例化之前的 $EXT->_call_hook('pre_controller');   //又mark一个点 $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start'); //终于实例化控制器了 $CI = new $class();   //钩子,不想多说了 $EXT->_call_hook('post_controller_constructor');   /* * ------------------------------------------------------ * Call the requested method * ------------------------------------------------------ */ // Is there a "remap" function? If so, we call it instead if (method_exists($CI, '_remap')) { $CI->_remap($method, array_slice($URI->rsegments, 2)); } else { // is_callable() returns TRUE on some versions of PHP 5 for private and protected // methods, so we'll use this workaround for consistent behavior if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI)))) { // Check and see if we are using a 404 override and use it. if ( ! empty($RTR->routes['404_override'])) { $x = explode('/', $RTR->routes['404_override']); $class = $x[0]; $method = (isset($x[1]) ? $x[1] : 'index'); if ( ! class_exists($class)) { if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) { show_404("{$class}/{$method}"); }   include_once(APPPATH.'controllers/'.$class.'.php'); unset($CI); $CI = new $class(); } } else { show_404("{$class}/{$method}"); } }   // 终于调用方法了,$this->load->view()把内容放到缓存区 call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); } $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); $EXT->_call_hook('post_controller');   //这里就是把缓存区的内容输出了 if ($EXT->_call_hook('display_override') === FALSE) { $OUT->_display(); }    
        //调用post_system的hook
    $EXT->_call_hook('post_system'); //关闭数据库的链接 if (class_exists('CI_DB') AND isset($CI->db)) { $CI->db->close(); }
  • 相关阅读:
    运维自动化轻量级工具pssh
    Linux下的tar压缩解压缩命令详解
    [shell] while read line 与for循环的区别
    Linux sed命令
    [转]linux awk命令详解
    Centos7上部署openstack ocata配置详解
    自动化运维工具——puppet详解(一)
    OpenStack 初探(一) -- All-In-One模式部署(初学OpenStack必备)
    shell中的重定向(输入输出)
    vim批量注释和反注释快捷键
  • 原文地址:https://www.cnblogs.com/xymqx/p/3921624.html
Copyright © 2020-2023  润新知