CodeIgniter2.1.0源码阅读(20120427更新)
本帖最后由 actionbi 于 2012-4-27 18:26 编辑初读Codeigniter代码,想探探高效框架的究竟。
感谢Hex给了个精华。
文章的结构修改为全部按照程序的执行顺序,按行读取。差不多相当于是给代码加注吧。
初读代码可能有很大的出入或者想不到的地方,这也是我发到论坛来的目的。希望大家给我指正。
mailto: actionbi2010@gmail.com 我会及时修正!
文件已楼层的形式发布,顶楼不写内容,只加链接。期待和大家交流。
[*]index.php 入口文件(结尾加载CodeIgniter.php)
[*]CodeIgniter.php 第51行 加载Common.php全局函数
[*]CodeIgniter.php 第51-66行 加载constans.php 系统常量
[*]CodeIgniter.php 第68-78行 定义错误处理机制和关闭全局过滤
[*]CodeIgniter.php 第78-109行 定义class前缀,程序运行时间和关闭安全模式
[*]CodeIgniter.php 第115-117行 加载并实例化Benchmark类 基准测试类
[*]CodeIgniter.php 第118-132行 加载并实例化Hook类 钩子扩展原理
[*]CodeIgniter.php 第133-145行 加载并实例化Config类 操作配置文件
[*]CodeIgniter.php 第159-165行 加载并实例化URI类 URI处理类
[*]CodeIgniter.php 第166-179行 加载并实例化Router类 设置路由
[*]CodeIgniter.php 第181-187行 加载并实例化Output类 处理输出
[*]CodeIgniter.php 第208-214行 加载并实例化Input类 提供相关数据进行处理函数
[*]CodeIgniter.php 第221-249行 加载并实例化Controller类 控制器基类
CodeIgniter2.1.0源码阅读(5)URL.php url处理类
本帖最后由 actionbi 于 2012-3-30 02:33 编辑在CodeIgniter.php中,第165行加载了URL类。目的是为了进行url的处理,类CI_URL也是个全局加载的类库,可以直接使用。
参数介绍:
$keyval = array(); //缓存的uri片段
var $uri_string;
/*
* 获取到的当前的URI的字符串
* 当你的URl为localhost/CodeIgniter/index.php?/welcome/index/var/4时
* $uri_string = welcome/index/var/4
*/
var $segments = array();//URI片段数组 数组键值从0开始
var $rsegments = array(); //重建索引的片段数组数组键值从1开始
附录:
url类中ci判断php的运行环境
CodeIgniter源码阅读URI.php中_fetch_uri_string()函数的解析
<?php
class CI_URI {
var $keyval = array();
var $uri_string;
/*
* 获取到的当前的URI的字符串
* 当你的URl为localhost/CodeIgniter/index.php?/welcome/index/var/4时
* $uri_string = welcome/index/var/4
*/
var $segments = array();//URI片段数组 数组键值从0开始
var $rsegments = array(); //重建索引的片段数组数组键值从1开始
function __construct(){
$this->config =& load_class('Config', 'core');
log_message('debug', "URI Class Initialized");
//加载了core/Config.php 也就是Config类,需要获取config文件中的设置
}
function _fetch_uri_string(){}//获取uri_sting详细见附录
function _set_uri_string($str){
//过滤url中的不可见的字符
$str = remove_invisible_characters($str, FALSE);
// If the URI contains only a slash we'll kill it
$this->uri_string = ($str == '/') ? '' : $str;
}
private function _detect_uri(){
//检测uri,经过此函数检测的uri将传送到_set_uri_string($str)
}
private function _parse_cli_args(){
$args = array_slice($_SERVER['argv'], 1);
return $args ? '/' . implode('/', $args) : '';
}
function _filter_uri($str){
//过滤url的参数
//过滤规则为 |^+$|i当uri的参数不符合条件时会报错
$bad = array('$', '(', ')', '%28', '%29');
$good = array('$', '(', ')', '(', ')');
}
function _remove_url_suffix(){
//取出uri的后缀
}
function _explode_segments(){
//将$this->uri_string 分割到数组中
//期间分割字符串要使用到_filter_uri($str)
}
function _reindex_segments(){
//为segements 重建索引
}
function segment($n, $no_result = FALSE){
//获取uri的一个 片段
return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
}
function rsegment($n, $no_result = FALSE){
//获取uri的一个片段
return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
}
function uri_to_assoc($n = 3, $default = array()){
return $this->_uri_to_assoc($n, $default, 'segment');
}
function ruri_to_assoc($n = 3, $default = array()){
return $this->_uri_to_assoc($n, $default, 'rsegment');
}
function _uri_to_assoc($n = 3, $default = array(), $which = 'segment'){
//uri片段转换成一个关联数组,据说是做cache,但是有点苦,函数懂了,但是用法不知
}
function assoc_to_uri($array){
//将uri片段的关联数组转换成uri
}
function slash_segment($n, $where = 'trailing'){
return $this->_slash_segment($n, $where, 'segment');
}
function slash_rsegment($n, $where = 'trailing'){
return $this->_slash_segment($n, $where, 'rsegment');
}
function _slash_segment($n, $where = 'trailing', $which = 'segment'){
}
function segment_array(){
return $this->segments;
//返回uri片段数组
}
function rsegment_array(){
return $this->rsegments;
//返回中间索引后uri片段数组
}
function total_segments(){
return count($this->segments);
//返回uri片段数
}
function total_rsegments(){
return count($this->rsegments);
}
function uri_string(){
return $this->uri_string;
//获取当前的uri字符串
}
function ruri_string(){
return '/'.implode('/', $this->rsegment_array());
}
}
?>
url类中ci判断php的运行环境
本帖最后由 actionbi 于 2012-3-30 02:27 编辑阅读ci代码过程中发现,处理URI会根据php的运行环境进行不同处理。
那么如何判断php的运行环境呢?
我们一般情况下,都是在apache下面运行我们的php程序,当然也有些人是用IIS环境的
我们要是想知道我们目前运行的环境是什么的话,那我们可以用函数php_sapi_name()来测试
代码:
<?php
echo php_sapi_name();
?>
在apache环境下面输出的结果是“apache2handler”;
在cgi模式下输出的结果是“cgi-fcgi”
要是在命令行模式下面运行的话,那么输出的结果是:”cli”
依据这个内容我们可以判断当前运行的环境是什么!
那么在命令行下怎么运行呢?
如下:
进入DOS 进入php.exe文件的地址 如我的是:d:/wamp/bin/php/php5.3.3/
然后输入php.exe “文件的绝对路径” 如:>php.exe d:/wamp/www/info.php
既可以了。
CI的分页不好用,么有thinkPHP的引用起来容易。而且到2.1了貌似还没有总页数的设计,要自己扩展吗?
CodeIgniter源码阅读URI.php中_fetch_uri_string()函数的解析
本帖最后由 actionbi 于 2012-3-30 13:36 编辑APPPATH/config/config.php中对于url 格式的拟定。
$config['uri_protocol'] = 'AUTO';
这个配置项目定义了你使用哪个服务器全局变量来拟定URL。
默认的设置是auto,会把下列四个方式轮询一遍。当你的链接不能工作的时候,试着用用auto外的选项。
'AUTO' Default - auto detects
'PATH_INFO' Uses the PATH_INFO
'QUERY_STRING' Uses the QUERY_STRING
'REQUEST_URI' Uses the REQUEST_URI
'ORIG_PATH_INFO' Uses the ORIG_PATH_INFO
CI_URI中的几个成员变量
$keyval = array(); //List of cached uri segments
$uri_string; //Current uri string
$segments //List of uri segments
$rsegments = array() //Re-indexed list of uri segments
获取到的current uri string 赋值到 $uri_string ,通过function _set_uri_string($str)。
获取到$str有几个选项,也就是_fetch_uri_string()的业务流程部分了
一、默认$config['uri_protocol'] = 'AUTO'时,程序会一次轮询下列方式来获取URI
(1)当程序在CLI下运行时,也就是在命令行下php文件时候。ci会这么获取URI
private function _parse_cli_args()
{
$args = array_slice($_SERVER['argv'], 1);
return $args ? '/' . implode('/', $args) : '';
}
//$_SERVER['argv'] 包含了传递给脚本的参数 当脚本运行在CLI时候,会给出c格式的命令行参数
截取到$_SERVER['argv']中除了第一个之外的所有参数
如果你在命令行中这么操作
php d:/wamp/www/CodeIgniter/index.php welcome index
_parse_cli_args() 返回一个 /welcome/index的字符串
(2)默认使用REQUEST_URI来探测url时候会调用 私有函数 _detect_uri()
(3)如果上面的两种方式都不能获取到uri那么会采用$_SERVER[‘PATH_INFO’]来获取
$path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO'); if (trim($path, '/') != '' && $path != "/".SELF) { $this->_set_uri_string($path); return; }
(4)如果上面三种方式都不能获取到,那么就使用$_SERVER[‘QUERY_STRING’]或者getenv[‘QUERY_STRING’]
$path =(isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); if (trim($path, '/') != '') { $this->_set_uri_string($path); return; }
(5)上面四种方法都不能获取到URI,那么就要使用$_GET数组了,没招了
if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '') { $this->_set_uri_string(key($_GET)); return; }
二、在config.php中设定了$config['uri_protocol'] ,那么 程序会自动执行相应的操作来获取uri
_parse_cli_args() 返回一个 /index.php/start/index的字符串
实际返回的是
/start/index 大道达人 发表于 2012-3-30 13:27 static/image/common/back.gif
_parse_cli_args() 返回一个 /index.php/start/index的字符串
实际返回的是
嗯,是的,我修正了。谢谢您指正
CodeIgniter源码阅读(6)Hook.php 钩子-扩展框架的核心
看了hook.php的源码,就知道CI使用hook来进行扩展的原理了。hook的基本知识http://codeigniter.org.cn/user_guide/general/hooks.html
CI中hook的使用经历了一个:开启hook,定义hook,调用hook,执行hook的过程。
手册中已经告知了开启、定义、调用的方法。那么hook的实现原理是啥呢。
<?phpif ( ! defined('BASEPATH')) exit('No direct script access allowed');
class CI_Hooks {
var $enabled = FALSE;
//开启hook的标志,默认是关闭的。APPPATH/config/config.php中的配置也是默认关闭的,如果想使用hook,要在config.php中开启。
var $hooks = array();
//在_initialize()函数初始化的过程中将APPPATH/config/hook.php中定义的hook数组,引用到$this->hooks;
var $in_progress = FALSE;
//当一个hook执行的时候,会给标记 $in_process = TRUE ,是为了防止同一个hook被同时调用。
function __construct()
{
$this->_initialize();
log_message('debug', "Hooks Class Initialized");
}
function _initialize()
{
//初始化hook
//判断config.php中是否开启hook
//include(hook.php),将文件里定义的hook数组引用到$this->hooks
//$this->enable = TRUE
}
function _call_hook($which = '')//pre_system
{
//以pre_system挂钩点为例,当调用_call_hook('pre_system')时
//确保$this->enable = TRUE && 定义了$this->hooks['pre_system']
//如果是二维数组就遍历,依次_run_hook($this->hooks['pre_system'][$val])
//如果是一维数组,那么直接_run_hook($this->hooks['pre_system'])
}
function _run_hook($data) //$data 是传递过来的hook数组
{
//$data 就是我们在APPPATH/config/hook.php 定义的hook数组
//$hook['pre_controller'] = array(
// 'class' => 'MyClass',
// 'function' => 'Myfunction',
// 'filename' => 'Myclass.php',
// 'filepath' => 'hooks',
// 'params' => array('beer', 'wine', 'snacks')
// );
取出data里面的数据,加载APPPATH.$data['filepath'].$data['filename'];
实例化钩子类,调用function。应用到示例中就是
$this->in_process = TRUE;
$Hook = newMyClass();
$Hook->Myfunction($params);
$this->in_process = FALSE;
}
}
?>
挂钩点可以挂多个hook,所以,当我们想扩展ci的时候,只需要将hook文件放到APPPATH文件夹下,然后
到APPPATH/config/hook.php中声明定义的hook的信息即可。那么系统运行到挂钩点的时候,会自动调用声明的hook。
如此一来便实现了可扩展性
顶一个!
CodeIgniter.php第51-66行 加载constans.php系统常量
本帖最后由 actionbi 于 2012-3-31 19:05 编辑代码用于处理加载系统define的常量。主要是一些预定义的权限。程序中可以直接使用。
命名很直观,所以不解释。
define('FILE_READ_MODE', 0644);
define('FILE_WRITE_MODE', 0666);
define('DIR_READ_MODE', 0755);
define('DIR_WRITE_MODE', 0777);
define('FOPEN_READ', 'rb');
define('FOPEN_READ_WRITE', 'r+b');
define('FOPEN_WRITE_CREATE_DESTRUCTIVE', 'wb'); // truncates existing file data, use with care
define('FOPEN_READ_WRITE_CREATE_DESTRUCTIVE', 'w+b'); // truncates existing file data, use with care
define('FOPEN_WRITE_CREATE', 'ab');
define('FOPEN_READ_WRITE_CREATE', 'a+b');
define('FOPEN_WRITE_CREATE_STRICT', 'xb');
define('FOPEN_READ_WRITE_CREATE_STRICT', 'x+b');