上一节简单实现了 CI 的类库扩展模型,所以 _ci_load_class 和 _ci_init_class 写的不是很完备。根据上节课的分析,当 system/libraries 目录下存在 Email.php, 然后在 application/libraies 目录下存在 My_Email.php 时就可以实现扩展类库的功能。除了扩展之外,我们还需要:

1)直接覆盖原始类

2)完全自定义类

很简单,按照约定,当不存在MY_开头的类库文件,加载类库的情况必定属于以上两种,如下所示

// 直接加载代码
$is_duplicate = FALSE;
foreach ($this->_ci_library_paths as $path) {
$filepath = $path.'libraries/'.$subdir.$class.'.php'; if ( ! file_exists($filepath)) {
continue;
} if (in_array($filepath, $this->_ci_loaded_files)) { if ( ! is_null($object_name)) {
$CI =& get_instance();
if ( ! isset($CI->$object_name)) {
return $this->_ci_init_class($class, '', $params, $object_name);
}
} $is_duplicate = TRUE;
log_message('debug', $class." class already loaded. Second attempt ignored.");
return;
} include_once($filepath);
$this->_ci_loaded_files[] = $filepath;
return $this->_ci_init_class($class, '', $params, $object_name);
}

其中 _ci_libraries_path 在初始构造函数中初始化如下:

$this->_ci_library_paths = array(APPPATH, BASEPATH);

注意顺序,先是 APPPATH, 然后再是 BASEPATH, 保证加载的顺序先是 application ,再是 system。

再来看一下 _ci_init_class 函数

public function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL) {

        if ($prefix == '') {
if (class_exists('CI_'.$class)) {
$name = 'CI_'.$class;
} elseif (class_exists(config_item('subclass_prefix').$class)) {
$name = config_item('subclass_prefix');
} else {
$name = $class;
}
} else {
$name = $prefix.$class;
} if ( ! class_exists($name)) {
log_message('error', "Non-existent class: ".$name);
show_error("Non-existent class: ".$class);
} $class = strtolower($class); // 这里对名字做了一个特殊的映射,针对 unit_test 就可以直接用 unit, 而非 unit_test
if (is_null($object_name)) {
$classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
} else {
$classvar = $object_name;
} // 保存 class 名和对象名, 以供判断某个类库是否加载
$this->_ci_classes[$class] = $classvar; $CI =& get_instance();
if ($config !== NULL) {
$CI->$classvar = new $name($config);
} else {
$CI->$classvar = new $name;
}

分析以上代码可以发现,为了直接覆盖原始的类库文件,对 $prefix ==‘’ 的情况作了进一步处理,判断是否存在 CI 或自定义MY_前缀的类,从而保证获得正确的类名。

实例名也考虑到了一种特殊的情况,比如加载 unit_test 类的时候,直接使用 unit 作为变量,这也值得我们借鉴和考虑!!!也就是说,在考虑到一般的情况下,还可以做更灵活的处理,对类名较长的类直接通过配置的方式指定实例名,非常简洁~

总结: 整个过程加载类库的设计就完成了,特别灵活和方便。

一步一步重写 CodeIgniter 框架 (10) —— 使用 CodeIgniter 类库(续)的更多相关文章

  1. 一步一步重写 CodeIgniter 框架 (9) —— 使用 CodeIgniter 类库

    通过前面几节的内容,我们从零开始搭建了一个非常方便的MVC框架,理解了 CodeIgniter 框架最核心的部分.然而一个框架的便利不仅仅在于提供一个MVC就可以了,它还必须具有较高的扩展性.下面将从 ...

  2. 一步一步重写 CodeIgniter 框架 (11) —— 使用 CodeIgniter 函数库

    在完成了CI框架的类库扩展后,很自然我们就会想到函数库的扩展.函数库的扩展在 CI 中称为 helper 函数与类有不同的地方,它不能继承,只能覆盖或者添加新的函数,或者直接完全新定义的一组函数. 由 ...

  3. **【ci框架】精通CodeIgniter框架

    http://blog.csdn.net/yanhui_wei/article/details/25803945 一.大纲 1.codeigniter框架的授课内容安排 2.codeigniter框架 ...

  4. CodeIgniter框架——知识要点汇总

    NO1.学习要点: 一.CodeIgniter 框架的简介 二.CodeIgniter 框架的安装 三.CodeIgniter 框架的目录结构分析 四.CodeIgniter 框架是如何工作的? 五. ...

  5. 一步一步重写 CodeIgniter 框架 (6) —— 实现在控制器Controller中加载View

    1. 控制器将模型类获得的数据,传递给视图进行显示,所以视图必须负责接收数据,另外重要的一点是当模型和视图分开后,多个模型的数据可以传递给一个视图进行展示,也可以说一个模型的数据在多个不同的视图中进行 ...

  6. 一步一步重写 CodeIgniter 框架 (5) —— 实现Controller,并加载Model

    CodeIgniter 框架采用MVC模式,而MVC模式中起纽带作用的就是C(控制器),在控制器的中通过加载模型获得数据,将数据传到视图中进行展示.本课将实现在控制器中加载模型. 1. 控制器的实现 ...

  7. 一步一步重写 CodeIgniter 框架 (4) —— load_class 管理多个对象实例的思路

    我们使用CodeIgniter 框架最主要是想利用其 MVC 特性,将模型.视图分开,并通过控制器进行统一控制.在尝试实现 MVC 模式之前,我们将实现其中一个对程序结构非常有用的技巧,就是 load ...

  8. 一步一步重写 CodeIgniter 框架 (3) —— 用面向对象重构代码

    前面两篇文章为了重点突出 CodeIgniter 框架的原理,程序的结构很乱,有很多全局变量,在这一课中我们采用面向对象的方法对原先代码进行重构. 到目前为止,程序主要完成的就是 URL 分析,并根据 ...

  9. 一步一步重写 CodeIgniter 框架 (1) —— url 如何映射到具体的方法

    CodeIgniter 框架最显著的特征就是 MVC 模式,它的做法就是提取 url 中的'分段', 映射到某个类的某个方法,从而由该方法来输出最终显示的页面内容.那么我们第一课中就是实现一个这样的原 ...

随机推荐

  1. Qtwebkit配置,设置交叉编译环境 - croop520的专栏 - 博客频道 - CSDN.NET

    Qtwebkit配置,设置交叉编译环境 - croop520的专栏 - 博客频道 - CSDN.NET Qtwebkit配置,设置交叉编译环境 分类: Qt Webkit 2012-04-12 15: ...

  2. TextBox控件只允许输入出生日期,并验证年龄不得小于18岁

    1.Body tag <form id="form1" runat="server"> <div> <asp:Label ID=& ...

  3. Unity 对象池 生产 保存

    Unity对象池主要是保存那些常用的物体,避免他们在不断销毁和创造中损坏性能. 主要思路为:创造物体时,判断是否存在,如果存在则调用并使其显示.如果不存在则创造一个新的. 当销毁时,调用协程延时隐藏物 ...

  4. OD调试篇1—Hello

    OD调试篇1—Hello 要求:通过OD将程序的标题“I love fishc.com”改为“I love you” 一.找到程序的标题“I love fishc.com” 1.把程序拖到OD运行出现 ...

  5. BZOJ 3175: [Tjoi2013]攻击装置( 匈牙利 )

    黑白染成二分图, 然后不能同时选的就连边, 最大匹配数为m, t为不能放的数目, 则题目所求最大点独立集为 n*n-m-t -------------------------------------- ...

  6. 基于Win7 Python2.7的Numpy安装包分享

    Numpy-1.9.2安装包: http://pan.baidu.com/s/1i3WZRoT 下载后双击安装即可! 另外分享一个安装教程,mark一下慢慢看: http://blog.csdn.ne ...

  7. WPF DataGrid模拟click实现效果

    WPF的DataGrid原生是不支持Click事件的,然而在开发过程中,经常遇到需要实现类似效果的. 举个栗子:表格第一列是一个CheckBox,需要实现功能点击行选中,再点击取消选中. 第一想法是R ...

  8. mongoDB初接触

    首先去官网http://www.mongodb.org/ 下载mongoDB 下载后解压D:\mongodb 创建两个新文件夹data以及log 新建一个文件命名为mongodb.cfg dbpath ...

  9. A package manager for Qt

    官网 http://www.qpm.io/ A package manager for Qt 注释:这个网站类似JavaScript的包管理器的网站https://www.npmjs.com/ 都是给 ...

  10. Sicily-1006

    一.  题意 这道题就是考排列组合吧,再来就是比较一下字符的下标算一下两个ranking的距离.然后我总结了一个排列和一个组合的实现方法,这道题直接用的是stl 里面的next_permutation ...