codeIgniter框架基本结构 (二)

[color=blue][b][size=medium]codeigniter/Base[/size][/b][/color]

[color=red]codeigniter/Base4.php[/color] 和 [color=red]codeigniter/Base5.php [/color]功能一样,只不过分别适用于 PHP4 和 PHP5 而已。其中定义了 CI_Base 类和一个非常重要的 get_instance() 函数。

get_instance() 函数返回一个 CI_Base 类在整个应用程序中的唯一实例。

这里有一个有趣的发现。Base4.php 和 Base5.php 中的 CI_Base 和 get_instance() 有这完全不同的实现。

在 Base4.php(对应 PHP4)中,CI_Base 直接继承自 CI_Loader。CI_Base 实例化时,将 自身的引用保存到了 CI_Base::$load 中。也就是说 CI_Base 实例的 $load 实际上指向自己。然后 $load 被复制到一个名为 $OBJ 的全局变量。

在 PHP4 版的 get_instance() 函数中,如果检查到 $CI(这是 CI_Base 的实例,也就是控制器的实例)存在,就返回 $CI,否则返回全局变量 $OBJ->load。但由于在 PHP4 中,$OBJ->load 实际上就是一个 CI_Base 的实例。所以。。。。所以。。。。。。还是返回了一个 CI_Base 的实例。真搞不懂作者为什么这样写,简直要让人发疯。

不管怎么样,应用程序其他地方调用 get_instance() 都会获得一个 CI_Base 的实例。

在 Base5.php(对应 PHP5)中,用一个 singleton 模式来解决了这个问题。因此 CI_Base 也不再需要从 CI_Loader 继承了。不过这也留下了隐患(CI_Loader 实例要什么时候获取呢?),所以在 CI_Base 的继承类 Controller 中,只好通过判断是否是运行 PHP5 来决定是不是要实例化一个 CI_Loader。

真的很无语啊,这种设计虽然可以用,但是很糟糕。在 PHP4 种,CI_Loader 的方法和成员变量暴露在了 CI_Base 中。如果应用程序不小心调用了这些方法或使用了这些成员变量。那么应用程序在 PHP5 中运行就会出错。


[size=medium][color=blue][b]Controller[/b][/color][/size]

Controller 类是所有控制器的基础类。

Controller 实例化时会将 CI_Input、CI_Benchmark、CI_Config、CI_URI、CI_Output、CI_Language 的实例复制到 Controller 实例的成员变量中。然后根据应用程序设置,自动载入文件。

但是这里作者显然没有处理好,所以不得不用 `global $IN, $BM, $CFG, $URI, $LANG, $OUT;` 这样的全局变量来传递几个重要的对象实例。

Controller 本身并没提供 model、helper 的载入服务。这些都由 CI_Loader 来提供。但是,CI_Loader 的各种载入服务,却又用 get_instance() 获取控制器的实例,然后调用 Controller(控制器都是 Controller 的继承类哦)的 _ci_initialize()、_ci_init_database() 等方法来做初始化。

神啊!救救我吧!这种错综复杂的关系,真的要人命啊!

Controller 的 $ci_is_loaded 成员变量用于保存已经载入的对象实例。所以每次用 Controller::_ci_load_model() 载入模块后,都要将该模块登记到 $ci_is_loaded,以避免重复载入。

Controller 里面大部分是一些初始化各种服务的方法,例如初始化数据库、Model 的方法。还有就是用 _ci_scaffolding() 调用 CodeIgniter 的“脚手架”功能。

对 Controller 的设计,没什么好说的,一个字:烂!


[size=medium][color=blue][b]CI_Loader[/b][/color][/size]

CI_Loader 提供各种载入服务,例如载入 Model、Helper、View 等。但是(我真的很痛恨“但是”这个词),CI_Loader 却需要 Controller 来完成初始化。那么又是谁来调用 CI_Loader 呢?答案是 Controller。

这种紧密的耦合,完全是没有必要的!

控制器开始执行
分析到这里,终于进入应用程序的代码了。应用程序控制器中,可以用 $this->load 来载入各种服务,然后就可以调用这些载入的服务了。

虽然 CodeIgniter 在 CI_Base、Controller 和 CI_Loader 上设计很糟糕,但开发者如果不在乎这些,那么开发过程还是很愉快的。

下面我们再来看看 CodeIgniter 主要服务的特点。
数据库访问
与大部分框架不同,CodeIgniter 的 Model 类没有提供数据库访问功能。所有数据库操作都是通过数据库驱动程序来进行的。

所有数据库驱动均继承自 CI_DB 类。等等,我怎么找不到 CI_DB 类的定义呢?因为 CI_DB 类是在 Controller 中用 `eval(‘class CI_DB extends CI_DB_driver { }’);` 这行代码来定义的。定义这样一个空壳,估计是作者为以后扩充数据库驱动留下的伏笔。

CodeIgniter 的数据库驱动,功能都很简单,和 AdoDB Lite 类似,但是缺乏 AdoDB Lite 那么多的扩展库。我个人认为反倒不如用 AdoDB Lite 来替换这部分。当然了,CodeIgniter 目前已经有不少数据库驱动了,所以替换成 AdoDB Lite 好处不多。

CodeIgniter 也提供了一个 ActiveRecord 实现,不过这个 ActiveRecord 可没有一点半点的“ORM”能力。但是 CodeIgniter 的 ActiveRecord 不需要为每一个数据表都构造一个实例。通常一个实例就可以处理多个数据表的操作。

例如 `$query = $this->db->get(‘mytable’);` 和 `$query = $this->db->get(‘mytable2′);` 就可以分别取得 mytable 和 mytable2 的数据。

说实话,作者可能用错了名字。

CodeIgniter 中的“ActiveRecord”实际上是表数据入口模式——TableDataGateway。

CodeIgniter 中的 ActiveRecord 基本上只是一个对数据表进行 CRUD 操作的公共接口。没有提供 RoR、CakePHP、FleaPHP 等框架具有的数据表关联自动处理能力。和自己写 SQL 相比,没什么优势。唯一的好处就是作者所说的可以让 ActiveRecord 来生成这些简单的 SQL 语句,而不用自己写,提高应用程序在不同数据库之间移植的能力。


[size=medium][color=blue][b]“脚手架”功能[/b][/color][/size]

CodeIgniter 中提供了基本的“脚手架”功能,可以用几行代码即实现一个对某个数据表进行 CRUD 的界面。这和 phpMyAdmin 中的数据浏览、编辑页面类似,当然功能要简单得多。

“脚手架”有什么实用价值,众说纷纭。但普遍认同的一点就是“脚手架”功能为处于开发初期的应用程序提供了管理数据的界面。开发者可以在后期替换掉“脚手架”的界面。

但是,CodeIgniter 也太简单了,就只有 CRUD 操作,还不如 phpMyAdmin 好用。
其他
CodeIgniter 还有许多其他的类和助手。这些类基本上都属于提供各种辅助服务的范畴。有些类很不错,像图片操作。但大部分类和助手实在太简单,缺乏实用价值。像数据验证助手,只能做很基本的验证,在绝大多数应用程序里面都不能满足要求。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值