通过前面几节的内容,我们从零开始搭建了一个非常方便的MVC框架,理解了 CodeIgniter 框架最核心的部分。然而一个框架的便利不仅仅在于提供一个MVC就可以了,它还必须具有较高的扩展性。下面将从 CodeIgniter 的官方文档中的顺序一步一步充实我们这个“丑陋” 的框架。

本课将实现 CodeIgniter 类库加载的模式,对应于http://codeigniter.org.cn/user_guide/general/libraries.html

1. library 函数

首先类库加载设计在 Loader 类中,函数命名为 library,如下所示

public function library($library = '', $params = NULL, $object_name = NULL) {

        if (is_array($library)) {

            foreach ($library as $class) {
$this->library($class, $params);
} return;
} if ($library == '' OR isset($this->_base_classes[$library])) {
return FALSE;
} if ( ! is_null($params) && ! is_array($params)) {
$params = NULL;
} $this->_ci_load_class($library, $params, $object_name);
}

与 model 类似,它首先判断传入的第一个参数是否为数组,如果是的话,就递归调用一次。

它通过调用 _ci_load_class 函数来实际加载具体的类。

2. _ci_load_class 函数实际加载

protected function _ci_load_class($class, $params = NULL, $object_name = NULL) {

        $class = str_replace('.php', '', trim($class, '/'));

        $subdir = '';
if (($last_slash = strrpos($class, '/')) !== FALSE) { // 提取出路径
$subdir = substr($class, 0, $last_slash + 1); // 提取出 class
$class = substr($class, $last_slash + 1);
} foreach (array(ucfirst($class), strtolower($class)) as $class) {
$subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php'; // class 扩展
if (file_exists($subclass)) {
$baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php'; if ( ! file_exists($baseclass)) {
log_message('error', 'Unable to load the requested class: '.$class);
show_error('Unable to load the requested class: '.$class);
} // 检查 class 是否加载过
if (in_array($subclass, $this->_ci_loaded_files)) {
if (! is_null($object_name)) {
$CI =& get_instance();
if ( ! isset($CI->$object_name)) {
return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
}
} $is_duplicate = TRUE;
log_message('debug', $class." class already loaded. Second attempt ignored.");
return; } include_once($baseclass);
include_once($subclass); $this->_ci_loaded_files[] = $subclass; return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
}
} if ($is_duplicate == FALSE) {
log_message('error', 'Unable to load the requested class: '.$class);
show_error("Unable to load the requested class: ".$class);
}
}

按照 CodeIgniter 的思路,首先会对加载函数的第一个参数路径进行拆分,得到具体的路径和文件名,因为文件名会有一些特殊的约定。

CodeIgniter 在设计的时候有个很重要的思想,就是区分 system 和 application 两种类型的代码,从而设计出灵活性很高的框架,那么针对 类库 而言,就是在 system 中提供一些常用的类库,然后给用户在这个基础上扩展或覆盖的权利,另外,也可以直接在

application 文件夹下设计出完全自定义的类。

本节主要实现 在原有类上进行扩展 的代码

1) 首先判断 application 文件夹下是否存在按照约定命名的扩展类库文件,即 subclass_prefix = 'MY_', 就判断是否存在 MY_类库名.php 文件

2)如果存在,则加载基类库文件,全部 include 之后,就可以 _ci_init_class 了

3. _ci_init_class 实例化 class

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

        if ($prefix == '') {
$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); $classvar = $class; $CI =& get_instance();
if ($config !== NULL) {
$CI->$classvar = new $name($config);
} else {
$CI->$classvar = new $name;
}
}

然后通过

$CI->$classvar = new $name($config);

成为 CI 核心对象的成员,从而就可以很方便的访问了~ $this->email->函数名();

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

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

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

  2. 一步一步重写 CodeIgniter 框架 (10) —— 使用 CodeIgniter 类库(续)

    上一节简单实现了 CI 的类库扩展模型,所以 _ci_load_class 和 _ci_init_class 写的不是很完备.根据上节课的分析,当 system/libraries 目录下存在 Ema ...

  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. NHibernate 的 ID 标识选择器

    在 Hibernate 中,每个对象需要一个标识 ID,通过这个标识 ID 建立对象与数据库中记录的对应关系. Nhibernate 提供了多种方式来建立这个 POID.基于不同的生成策略,可以选择更 ...

  2. Php 使用 fsockopen发送http请求

    <?php function HTTP_Post($URL,$data, $referrer="") { // parsing the given URL $URL_Info ...

  3. poj 2533 Longest Ordered Subsequence(线性dp)

    题目链接:http://poj.org/problem?id=2533 思路分析:该问题为经典的最长递增子序列问题,使用动态规划就可以解决: 1)状态定义:假设序列为A[0, 1, .., n],则定 ...

  4. Flex XML搜索、匹配

    - <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx=" ...

  5. Android蓝牙开发深入解析

    1. 使用蓝牙的响应权限  代码如下: <uses-permission android:name="android.permission.BLUETOOTH" /> ...

  6. 解决Windows 7下IE11无法卸载、无法重新安装,提示安装了更新的IE版本

    2013年12月14日 iefans 有用户反馈在Windows 7系统上安装IE11时发现安装程序似乎出了问题,等待了很长时间都没有响应之后就断开了电脑的电源.之后IE11浏览器虽然能使用,却无法安 ...

  7. LeetCode 二叉树后序遍历(binary-tree-postorder-traversal)

    Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...

  8. Java排序之排序大综合

    一.最近写了一些排序,于是和和大家分享一下:(默认都是从小到大排序) 二.冒泡排序 1.什么是冒泡排序:原理是临近的两个数比较大小,将较大的数往后移,这样遍历一趟数组以后,最大的数就排在的最后面(时间 ...

  9. json格式字符串与java.util.Map的互转(借助于jackson.jar)

    package com.test.javaAPI.json; /** * json工具类 * * @author Wei * @time 2016年10月2日 下午4:25:25 */ public ...

  10. python成长之路15

    一:JavaScript: JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的 ...