CI代码阅读
为什么选择CI 官网给出的理由
- 你想要一个小巧的框架;
- 你需要出色的性能;
- 你需要广泛兼容标准主机上的各种 PHP 版本和配置;
- 你想要一个几乎零配置的框架;
- 你想要一个不需使用命令行的框架;
- 你想要一个不想被编码规则的条条框框限制住的框架;
- 你对 PEAR 这种庞然大物不感兴趣;
- 你不想被迫学习一种新的模板语言(当然如果你喜欢,你可以选择一个模板解析器);
- 你不喜欢复杂,追求简单;
- 你需要清晰、完整的文档。
如果你用php 开发那么你一定希望程序能够快速,稳定,简单的搭建起来,相比其他框架CI 太简单了。
CI是一个入门框架。
CI 小巧精简也确定了他比其他框架快一点点。
0x01.入口文件定义了一堆常量 ,最后引入核心文件
require_once BASEPATH.'core/CodeIgniter.php';
0x002.在 CodeIgniter.php中拦截一些报错
set_error_handler('_error_handler'); set_exception_handler('_exception_handler'); register_shutdown_function('_shutdown_handler');
建立我们的主角 CI_Controller.然后大臣们也开始工作并注入到容器中.CI_Controller要做的就是控制反转。所以你可以在 controller 中使用 $this->input->get('');
$BM =& load_class('Benchmark', 'core'); $EXT =& load_class('Hooks', 'core'); $CFG =& load_class('Config', 'core'); $UNI =& load_class('Utf8', 'core'); $URI =& load_class('URI', 'core'); $OUT =& load_class('Output', 'core'); $IN =& load_class('Input', 'core'); $SEC =& load_class('Security', 'core'); $LANG =& load_class('Lang', 'core');
0x03.Router 开始工作
$e404 = FALSE; $class = ucfirst($RTR->class); $method = $RTR->method; if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php')) { $e404 = TRUE; } else { require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php'); if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method)) { $e404 = TRUE; } elseif (method_exists($class, '_remap')) { $params = array($method, array_slice($URI->rsegments, 2)); $method = '_remap'; } elseif ( ! method_exists($class, $method)) { $e404 = TRUE; } /** * DO NOT CHANGE THIS, NOTHING ELSE WORKS! * * - method_exists() returns true for non-public methods, which passes the previous elseif * - is_callable() returns false for PHP 4-style constructors, even if there's a __construct() * - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited * - People will only complain if this doesn't work, even though it is documented that it shouldn't. * * ReflectionMethod::isConstructor() is the ONLY reliable check, * knowing which method will be executed as a constructor. */ elseif ( ! is_callable(array($class, $method))) { $reflection = new ReflectionMethod($class, $method); if ( ! $reflection->isPublic() OR $reflection->isConstructor()) { $e404 = TRUE; } } } if ($e404) { if ( ! empty($RTR->routes['404_override'])) { if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $error_class, $error_method) !== 2) { $error_method = 'index'; } $error_class = ucfirst($error_class); if ( ! class_exists($error_class, FALSE)) { if (file_exists(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php')) { require_once(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php'); $e404 = ! class_exists($error_class, FALSE); } // Were we in a directory? If so, check for a global override elseif ( ! empty($RTR->directory) && file_exists(APPPATH.'controllers/'.$error_class.'.php')) { require_once(APPPATH.'controllers/'.$error_class.'.php'); if (($e404 = ! class_exists($error_class, FALSE)) === FALSE) { $RTR->directory = ''; } } } else { $e404 = FALSE; } } // Did we reset the $e404 flag? If so, set the rsegments, starting from index 1 if ( ! $e404) { $class = $error_class; $method = $error_method; $URI->rsegments = array( 1 => $class, 2 => $method ); } else { show_404($RTR->directory.$class.'/'.$method); } } if ($method !== '_remap') { $params = array_slice($URI->rsegments, 2); }
这个代码是从 配置中读取路由参数,然后根据uri 将请求路由到指定的 action 中,将逻辑交由action处理。
这个 action是被定义到继承CI_Controller的控制类中,所以他可以通过 $this 使用全局已经注入的依赖。
依赖注入。
0X04.非Controller中如何使用依赖,答案是还是通过CI_Controller。
get_instance() 可以直接拿到这个容器。可以在common.php 中使用依赖方法。
function &get_instance() { return CI_Controller::get_instance(); }
就连CI中的Model 也是从CI_Controller中找依赖database