Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51208
  • 博文数量: 12
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 142
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-16 21:18
文章分类

全部博文(12)

文章存档

2015年(1)

2014年(1)

2013年(10)

我的朋友

分类: PHP

2013-09-19 00:48:42

     上一节我们研究了它的入口文件,那么接下来我们进入它的部引导类,就是codeigniter.php文件,这个文件略大,它的主要工作是统一全局的过程,因此,它的调用过程就是我们这个框架的执行流程.但是这个框架屏蔽了太多的细节问题,要探究具体的细节还得去具体的某一个类,因此,我们在研究这个类的时候,只需要知道它调用的哪些部分是为了完成哪些功能,而不必太过于着急去研究这个类的功能.我们后面会再次分析它的具体实现方式的.
    它的功能如下:
1.设置配置项,配置是非常重要的,而配置往往又及其的复杂,有可能来自于写入文件的配置项,有可能来自于数据库中,还有可能被动态的修改,因此,考虑到配置项来源的复杂性,那么你是怎么处理的呢?ci框架通过一个配置类来处理它.
2.加载各个功能类,在加载完相应类之后有可能需要调用相应的函数来进行简单操作,毕竟一个类的构造函数不可能完成所有的工作.
3.我们需要仔细权衡的就是它加载各个类的顺序和各个类的功能,比如说在分析url的这一功能上,判断url的模式,防注入,动态生成url,url出现问题的解决方式等等.其实呢,随着我们解析的深入,这些问题都会给出一个解决方案,不一定最好,但是绝对可行.
废话不多说,直接上源码,另外就是我写的注释,感觉只要大家懂得php的语法和汉字,看懂是没问题的,如果有错误之处,也请指出.
4.该流程的主要是判断该类的该方法是否存在,然后调用相应的方法即可了 .当然路由类势必要起到很大的作用.

点击(此处)折叠或打开

  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2.     //定义CI的版本.
  3.     define('CI_VERSION', '2.0');
  4.     //加载全局函数.
  5.     require(BASEPATH.'core/Common'.EXT);
  6.     //加载应用程序的常量.
  7.     require(APPPATH.'config/constants'.EXT);
  8.     //定义错误处理函数
  9.     set_error_handler('_exception_handler');
  10.     //判断PHP版本.
  11.     if ( ! is_php('5.3'))
  12.     {
  13.         @set_magic_quotes_runtime(0);
  14.     }

  15.     //设置子类的前缀,这在多个应用同时出现时比较有用,比如可以设置"A_"和"B_"来区分.
  16.     if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '')
  17.     {
  18.         get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
  19.     }

  20.     //设置一个自由的脚本执行时间限制.
  21.     if (function_exists("set_time_limit") == TRUE AND @ini_get("safe_mode") == 0)
  22.     {
  23.         @set_time_limit(300);
  24.     }
  25.     //时间开始,开始计时,这个具体功能到基准测试类再仔细看.
  26.     $BM =& load_class('Benchmark', 'core');
  27.     $BM->mark('total_execution_time_start');
  28.     $BM->mark('loading_time:_base_classes_start');
  29.     //实例化钩子类.什么是钩子和钩子的作用及其实现在钩子类里仔细分析.
  30.     $EXT =& load_class('Hooks', 'core');
  31.     //是否有系统开始前的钩子.
  32.     $EXT->_call_hook('pre_system');
  33.     //实例化配置类.
  34.     $CFG =& load_class('Config', 'core');
  35.     //我们是否需要手工去修改配置项
  36.     if (isset($assign_to_config))
  37.     {
  38.         $CFG->_assign_to_config($assign_to_config);
  39.     }
  40.     //实例化UTF8类.
  41.     $UNI =& load_class('Utf8', 'core');
  42.     //实例化URI类.
  43.     $URI =& load_class('URI', 'core');
  44.     //实例化路由类,并且设置路由.
  45.     $RTR =& load_class('Router', 'core');
  46.     $RTR->_set_routing();
  47.     //在index.php里可以覆盖默认的路由.
  48.     if (isset($routing))
  49.     {
  50.         $RTR->_set_overrides($routing);
  51.     }
  52.     //实例化输出类,具体功能到output类里分析.
  53.     $OUT =& load_class('Output', 'core');
  54.     //是否有相应的缓存,如果有缓存文件,则直接使用相应的缓存文件.
  55.     if ($EXT->_call_hook('cache_override') === FALSE)
  56.     {
  57.         if ($OUT->_display_cache($CFG, $URI) == TRUE)
  58.         {
  59.             exit;
  60.         }
  61.     }
  62.     //加载input类.
  63.     $IN    =& load_class('Input', 'core');
  64.     //加载语言类.
  65.     $LANG =& load_class('Lang', 'core');

  66.     //引入基控制器
  67.     require BASEPATH.'core/Controller'.EXT;
  68.     //得到控制器的实例,这个方法会经常用到.
  69.     function &get_instance()
  70.     {
  71.         return CI_Controller::get_instance();
  72.     }

  73.     //如果存在子类应用的基控制器,则加载它.
  74.     if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller'.EXT))
  75.     {
  76.         require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller'.EXT;
  77.     }

  78.     
  79.     //使用路由类来加载具体的控制器,如果文件不存在,则报错.
  80.     if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().EXT))
  81.     {
  82.         show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.');
  83.     }

  84.     include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().EXT);

  85.     //为测试开始计时.
  86.     $BM->mark('loading_time:_base_classes_end');


  87.     //安全检测,通过路由取得的类和方法进行判断.
  88.     $class = $RTR->fetch_class();
  89.     $method = $RTR->fetch_method();
  90.     //如果类或方法有问题,则定义404 not found.
  91.     //这里的404涉及到http协议,请参考其他内容.
  92.     if ( ! class_exists($class)
  93.         OR strncmp($method, '_', 1) == 0
  94.         OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
  95.         )
  96.     {
  97.         show_404("{$class}/{$method}");
  98.     }

  99.     //在控制器之前是否要执行钩子?
  100.     $EXT->_call_hook('pre_controller');

  101.     //实例化请求的控制器类并且开始计时.
  102.     $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');

  103.     $CI = new $class();

  104.     //在控制器的构造时是否需要执行钩子.
  105.     $EXT->_call_hook('post_controller_constructor');

  106.     //调用钩子定义的函数,
  107.     //分析方法是否被重写,即开启了重写模式.如果是我们调用后者.
  108.     if (method_exists($CI, '_remap'))
  109.     {
  110.         $CI->_remap($method, array_slice($URI->rsegments, 2));
  111.     }
  112.     else
  113.     {
  114.         
  115.         //is_callable()在php 5的某些版本里面,对于private和protected方法会返回true.
  116.         if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))
  117.         {
  118.             //如果该方法根本就不存在,进行相应的处理.
  119.             if ( ! empty($RTR->routes['404_override']))
  120.             {
  121.                 $x = explode('/', $RTR->routes['404_override']);
  122.                 //$x的第一个参数为相应的类.
  123.                 $class = $x[0];
  124.                 //$x的第二个参数为相应的方法,如果没有默认为index
  125.                 $method = (isset($x[1]) ? $x[1] : 'index');
  126.                 if ( ! class_exists($class))
  127.                 {
  128.                     if ( ! file_exists(APPPATH.'controllers/'.$class.EXT))
  129.                     {
  130.                         show_404("{$class}/{$method}");
  131.                     }

  132.                     include_once(APPPATH.'controllers/'.$class.EXT);
  133.                     unset($CI);
  134.                     $CI = new $class();
  135.                 }
  136.             }
  137.             else
  138.             {
  139.                 show_404("{$class}/{$method}");
  140.             }
  141.         }

  142.         
  143.         
  144.         //任何一个uri段会被会被便利的通过该方法调用.
  145.         call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
  146.     }


  147.     //在方法执行完之后记录时间.
  148.     $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');

  149.     //调用post_controller的钩子.
  150.     $EXT->_call_hook('post_controller');

  151.     //是否有展示的时候被重写的钩子.
  152.     if ($EXT->_call_hook('display_override') === FALSE)
  153.     {
  154.         $OUT->_display();
  155.     }

  156.     //在post_system里是否有钩子.
  157.     $EXT->_call_hook('post_system');

  158.     //如果数据库未关闭,则关闭数据库.
  159.     if (class_exists('CI_DB') AND isset($CI->db))
  160.     {
  161.         $CI->db->close();
  162.     }

阅读(1018) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~