首页 > 代码库 > CodeIgniter框架——源码分析之CodeIgniter.php

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

CodeIgniter.php中加载了很多外部文件,完成CI的一次完整流程。

<?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.1.4‘);    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啦    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()    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();    }     $EXT->_call_hook(‘post_system‘);        //关闭数据库的链接    if (class_exists(‘CI_DB‘) AND isset($CI->db))    {        $CI->db->close();    }