让CodeIgniter自动加载所有自定义类

4 Comments

此文主要是提出一种让CodeIgniter自动加载所有自定义类的办法,即lazyloading。(只适用于没有带参数的构造函数的类)

先举个例子,如果我在一个controller中想调用某自定义的library,一般来讲需要两步:
1.  $this->load->library(“mylib”);
2.  $this->mylib->myfunction();

虽然第一步不是每次都要调用,但至少要在使用前初始化一次。当需要的library比较多时,假如再加上需要的model类,那就有点烦人了。所以,我们要做的就是去掉第一步,不管在controller,library还是model中,让codeigniter自动load需要的类,这样我们就能更专注于业务逻辑,而不用考虑载入的问题。

大家都知道,php5中预定义了__get()方法来获取属性,这个方法不是默认存在的,需要我们手工添加到类里面去。我们就利用这个方法来实现自动加载,首先需要在system/library/Controller和Model两个codeigniter文件中加上__get()方法,代码如下:

function __get ($name){
	if ($name == "config") return;
	$var =&wxMagicGet($name);
	return $var;
}

而wxMagicGet方法可以定义在一个你自己的helper文件中,代码如下:

function &wxMagicGet($name){
	if ($name == "db"){
		$CI = &get_instance();
		$CI->load->database();
		return $CI->$name;
	}
 
	if (!wxGetLoadingInfo($name, $type, $mpath)) return null;
 
	$CI = &get_instance();
	if ($type == 1){
		$CI->load->library($mpath.$name);
	} else if ($type == 2){
		$CI->load->model($mpath.$name);
	} else {
		return null;
	}
	return $CI->$name;
}
 
function wxGetLoadingInfo($name, &$type, &$mpath){
	static $pathmap = array();
	$filename = $name;
	if (strripos($name, ".php") === FALSE){
		$filename .= ".php";
	}
 
	return _find_where($filename, $type, $mpath);
}
 
function _find_where($name, &$type, &$mpath){
	//find in app model
	$type = 2;
	if (_find_where_path($name, APPPATH."models/", $mpath)) {
		$mpath = substr($mpath, strlen(APPPATH."models/"));
		return true;
	}
 
	//find in app library
	$type = 1;
	if (_find_where_path($name, APPPATH."libraries/", $mpath)) {
		$mpath = substr($mpath, strlen(APPPATH."libraries/"));
		return true;
	}
 
	//find in base library
	$type = 1;
	if (_find_where_path($name, BASEPATH."libraries/", $mpath)) {
		$mpath = substr($mpath, strlen(BASEPATH."libraries/"));
		return true;
	}
 
	return false;
}
 
function _find_where_path($name, $path, &$mpath){
	if (file_exists($path . $name)){
		$mpath = $path;
		return true;
	}
 
	if (file_exists($path . ucfirst($name1))){
		$mpath = $path;
		return true;
	}
 
	if (file_exists($path . strtoupper($name))){
		$mpath = $path;
		return true;
	}
 
	//更深入的查找所有子目录
	$found = false;
	if ($handle = @opendir($path)) {
		while (false !== ($file = readdir($handle))) {
			if ($file != "." && $file != "..") {
				$child = $path.$file;
				if(is_dir($child)) {
					if (_find_where_path($name, $child . "/", $mpath)){
						$found = true;
						break;
					}
				}
			}
		}
		closedir($handle);
	}
	return $found;
}

好,一个自动查找并加载的helper就写好了,记得将这个helper放到application/config/autoload.php文件中,这样codeigniter在每次运行时会自动初始化它。

以后我们开发时不管在哪都可以直接调用需要的类,不需要先load了。:)
Controller里直接写:$this->classname->function(xxx)就行,
Library里需要先初始化codeigniter资源,如:$this->obj = &get_instance();
之后也可直接写:$this->obj->classname->function(xxx)

关于codeigniter的框架结构及初始化程序流程,可以参考下面两篇文章:
codeigniter是如何实现mvc模式以及单一入口
codeIgniter之优缺点

codeigniter手册请查看官方网站:http://codeigniter.org.cn/user_guide/index.html

4 Comments (+add yours?)

  1. 音速
    Feb 04, 2010 @ 11:38:45

    娘啊,你真是强啊,php都研究,我太渺小了

    [Reply]

    Ting Reply:

    哈哈 介四我相公罗夕同学写的啦~~~你莫激动呀

    [Reply]

  2. 音速
    Feb 04, 2010 @ 17:59:06

    我刚换了个系统,发现你的页面在ie6下错版.这个问题就要研究下,你是想用户体验升级,还是……

    [Reply]

    Ting Reply:

    恩 这个皮肤是临时从网上下的 等过完年我会自己设计个新的 到时一定会兼容IE6的 呵呵 虽然我不太擅长这个吧 谢谢提醒啊~

    [Reply]

Leave a Reply