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

在上一课中,我们用面向对象的方法大大简化了程序的结构,将主要工作放在两个类中进行 ,URI 和 Router 类。 但是在 Router 类的构造函数中为了获得 uri 的实例,我们使用了 global 关键字,如下所示:

 class CI_Router {
...
function __construct() {
global $URI;
$this->uri = &$URI;
}
....
}

当程序的结构变得很复杂时,用 global 关键词会使得全局变量的管理非常乱,而且这些全局变量往往对应于一个具体功能类的实例,在实例化之前需要加载相应class的 php 文件。

1. 问题提炼和分析

  根据上述分析,关键的问题是

  1)需要一个集成管理这些全局变量的地方

  2)这些类的实例产生时,很方便的加载对应的 php 文件。

  集成管理变量一般采用 类的方式,然后通过该类的一个实例(唯一一个)获取需要的变量,这个实例往往称为核心全局变量,如discuz 中的 $discuz_core 变量;

  另一种方式,就是函数,但是函数没法存储成员变量,所以必须利用一个很有用的语法特性,就是 static 静态变量。

  在这里,我们采用第二种更简洁的方式。

2. 实现步骤

  1) 定义函数的接口

    函数名为 load_class , 我们希望通过传递一个字符串参数,就能获得对应的实例,比如 load_class('Router'); 就可以得到 上一课中的 $RTR 变量的引用。

    所以函数的接口为:    

function &load_class($class) {}

  2) 定义存储这些重要类实例全局变量的静态数组 

static $_classes = array();

那么该数组,存储的键值对就是 ’Router' => $RTR  的样子。

  3) 具体的逻辑

 // 当加载需要的类实例时,如果不是第一次加载,那么 $_classes 数组中肯定存放了需要的实例,直接返回即可
if (isset($_classes[$class])) {
return $_classes[$class];
} // 在我们的框架中,每个类实例都有前缀CI_
$name = 'CI_'.$class; if (file_exists($class.'.php')) {
require($class.'.php');
} else {
exit('Unable to locate the class');
} $_classes[$class] = new $name();
return $_classes[$class];

3. 修改主逻辑代码  

 <?php
/**
* 框架主入口文件,所有的页面请求均定为到该页面,并根据 url 地址来确定调用合适的方法并显示输出
*/
require('Common.php'); $URI =& load_class('URI');
$RTR =& load_class('Router'); $RTR->set_routing(); $class = $RTR->fetch_class();
$method = $RTR->fetch_method(); $CI = new $class(); call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); class Welcome { function hello() {
echo 'My first Php Framework!';
} function saysomething($str) {
echo $str.", I'am the php framework you created!";
}
}

另外,所有需要用到这些全局变量的地方,调用 load_class 就可以了,所以 Router 构造函数的地方使用 load_class.

 function __construct() {
$this->uri =& load_class('URI');
}

4. 测试结果

  访问 http://localhost/learn-ci/index.php/welcome/hello , 可以看到输出为:

  hello, I'am the php framework you created!

一步一步重写 CodeIgniter 框架 (4) —— load_class 管理多个对象实例的思路的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 一步一步重写 CodeIgniter 框架 (12) —— 代码再重构,回归 CI

    第一课中搭建的基本的 框架模型, 只有一个 index.php 作为执行文件,按这种方式最不稳定的因素就是路径的问题. 我们经常需要通过合适的参数,比如 load_class('output') 或 ...

  7. 一步一步重写 CodeIgniter 框架 -- 原因和思路

    CodeIgniter 是一个非常轻量级的 PHP 框架,说是轻量级,最新版的代码只有不到2M. 其最重要的特点就是 MVC 模式来编写代码,如果大家看过一些用 PHP 来编写网站的书籍或教程,无一例 ...

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

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

  9. 一步一步重写 CodeIgniter 框架 (2) —— 实现简单的路由功能

    在上一课中,我们实现了简单的根据 URI 执行某个类的某个方法.但是这种映射没有扩展性,对于一个成熟易用的框架肯定是行不通的.那么,我们可以让 框架的用户 通过自定义这种转换来控制,用 CI 的术语就 ...

随机推荐

  1. jQuery源码,匿名函数自执行

    jQuery框架的首尾是这样写的()(), (function(window){//这个window是个入参,随便起个名字都行 //这里面全都是js代码 })(window)//这个括号里的windo ...

  2. Objective-c 截取子字符串

    NSString类中提供了这样三个方法用于获取子字符串: – substringFromIndex: – substringWithRange: – substringToIndex: 它们该怎么使用 ...

  3. 用JS判断用户使用的是手机端还是pc端访问

    最近项目中用到一个应用,当访问同一个网站地址的时候,例如:www.xxx.com的时候,如果当前客户端是pc则跳转到专注于pc的部分,如果当前客户机是手机,则跳转到专注于手机的部分,秉承一贯的习惯,b ...

  4. iTextSharp.text的一个使用,主要用来创建PDF

    using iTextSharp.text; //创建一个字体来使用和编码格式 BaseFont baseFont = BaseFont.CreateFont("C:\\Windows\\F ...

  5. javascript学习(10)——[知识储备]链式调用

    上次我们简单的说了下单例的用法,这个也是在我们java中比较常见的设计模式. 今天简单说下链式调用,可能有很多人并没有听过链式调用,但是其实只要我简单的说下的话,你肯定基本上都在用,大家熟知的jQue ...

  6. Linux/Mac OS 下 批量提交 新增文件到SVN 服务器

    命令行下操作svn没有使用界面形式的TortoiseSVN直观,但是不管怎样,命令行下操作svn还是有它的有点,如果你碰到一次需要svn add许多个文件怎么办?下面的命令可以帮助你解决这个问题 一次 ...

  7. ThinkPHP文件上传类

    TP框架自带文件上传类使用: 类文件在ThinkPHP/Library/Think/默认在目录下 public function upload(){ $upload = new \Think\Uplo ...

  8. QGraphicsTextItem中的文字对齐

    QGraphicsTextItem类可以放到QGraphicsScene或者QGraphicsItem上,用来显示格式化的文本内容,如HTML,当然纯文本也可以显示.如果只是显示纯文本,可以使用QGr ...

  9. POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

    思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络 ...

  10. PLSQL Developer使用技巧整理(转)

    一.工具-首选项-用户界面-编辑器-其它-显示行号二.工具-首选项-窗口类型-SQL窗口-显示隔号(行号) 在使用PL/SQL Developer对Procedure进行Debug时,突然发现无法Se ...