actionbi 发表于 2012-3-29 17:47:02

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类 控制器基类

actionbi 发表于 2012-3-29 17:47:58

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('&#36;',        '&#40;',        '&#41;',        '&#40;',        '&#41;');
                }
        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());
                }
}

?>

actionbi 发表于 2012-3-29 17:48:13

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
既可以了。

ㄟ香消玉落 发表于 2012-3-29 21:57:42

CI的分页不好用,么有thinkPHP的引用起来容易。而且到2.1了貌似还没有总页数的设计,要自己扩展吗?

actionbi 发表于 2012-3-30 02:32:55

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

大道达人 发表于 2012-3-30 13:27:03

_parse_cli_args() 返回一个 /index.php/start/index的字符串

实际返回的是
/start/index

actionbi 发表于 2012-3-30 13:38:04

大道达人 发表于 2012-3-30 13:27 static/image/common/back.gif
_parse_cli_args() 返回一个 /index.php/start/index的字符串

实际返回的是


嗯,是的,我修正了。谢谢您指正

actionbi 发表于 2012-3-30 15:15:42

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。
如此一来便实现了可扩展性

justdoit 发表于 2012-3-30 17:00:05

顶一个!

actionbi 发表于 2012-3-31 18:51:09

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');

页: [1] 2 3 4
查看完整版本: CodeIgniter2.1.0源码阅读(20120427更新)