用户
 找回密码
 入住 CI 中国社区
搜索
查看: 4400|回复: 1
收起左侧

CI分析之调用机制(2)[加载的类的原理和使用方法]

[复制链接]
发表于 2012-1-8 18:11:31 | 显示全部楼层 |阅读模式
原文地址: http://www.mycode114.com/archives/140
上一篇我知道了,CI加载了哪些类文件.
那么这些类文件在哪里加载进来的呢,我们可以怎么用它. 和扩展相似的类呢
在Index.php中加载了Codeigniter.php
在这个文件中引用加载函数, 在CI中有大量的引用方式. 这个我会在以后的文章中分析.
PHP复制代码
$BM =& load_class('Benchmark', 'core');//调试性能的类
$EXT =& load_class('Hooks', 'core');//扩展类
$CFG =& load_class('Config', 'core');//配置类
$UNI =& load_class('Utf8', 'core');//utf8
$URI =& load_class('URI', 'core');//url
$RTR =& load_class('Router', 'core');//路由类
$OUT =& load_class('Output', 'core');//输出类
$SEC =& load_class('Security', 'core');//安全过滤类
$IN =& load_class('Input', 'core');//输入类
$LANG =& load_class('Lang', 'core');//语言类
复制代码

SO,默认加载这些类都是在Codeigniter.php这个文件加以load_class的方式加载的.
举一反三,如果我要扩展CI中没有的内核机制, 在core文件夹下新建我要的类文件, 在codeigniter中用load_class()的方式加载就行了.
只要是通过load_class加载的类文件,我就可以用如下的方式在控制器,和模板里用了
PHP复制代码
print_r($this->benchmark);
print_r($this->hooks);
print_r($this->config);
print_r($this->utf8);
print_r($this->uri);
print_r($this->router);
print_r($this->output);
print_r($this->security);
print_r($this->input);
print_r($this->lang);
print_r($this->load);
global $BM;//可以用它的变量来引用对象,不建议
print_r($BM);
exit;
复制代码

所以默认我们就可以用加载的这11个对象了,用得最多的当然是$this->load->view();因为它是加载模板的方法.
接下来我们来分析框架的load_class方法,它是如何加载我们要用到的类文件的.
在公共函数文件Common.php的load_class()方法中利用静态变量,实现单件模式. 每个类文件只加载一次
PHP复制代码
static $_classes = array();
 
// Does the class exist?  If so, we're done...
if (isset($_classes[$class]))
{
        return $_classes[$class];
}
复制代码

load_class方法会按优先级加载类文件,而且只加载一次.
问题来了,既然load_class已经实现单件模式,为什么还要用is_loaded()跟踪加载的类呢?
PHP复制代码
// Keep track of what we just loaded
is_loaded($class);
复制代码

它的作用就是用它来给将已经加载的类文件, 在控制器文件Controller.php中传给$this这个大对象
加载的类储存在$_is_loaded中
PHP复制代码
static $_is_loaded = array();
if ($class != '')
{
        $_is_loaded[strtolower($class)] = $class;
}
 
return $_is_loaded;
复制代码

再通过循环把它传给$this
PHP复制代码
foreach (is_loaded() as $var => $class)
{
        $this->$var =& load_class($class);
}
复制代码

so,我就可以用到上面代码中的各种类的方法了.
在控制器中我是可以这样用的,
比如
PHP复制代码
class Home extends CI_Controller{
function index(){
print_r($this->load);
}
}
复制代码

在是如果我要在helper中写函数,函数中要用到系统提供的对象方法呢.
手册上是这样用的.
PHP复制代码
//加载配置文件
$CI =& get_instance();
$CI->config->load('dw/head_load',true);
$arr = $CI->config->config['dw/head_load'];
复制代码

为什么不能用$this->config呢,因为helper是函数,没有像控制器那样去继承 CI_Controller
所以只有通过Codeigniter的一个函数去调用CI_Controller的get_instance()方法
PHP复制代码
// Load the base controller class
require BASEPATH.'core/Controller.php';
 
function &get_instance()
{
        return CI_Controller::get_instance();
}
复制代码

在CI_Controller中的代码如下:
PHP复制代码
private static $instance;
 
public function __construct()
{
        //成功对接$this变量,呵呵
        self::$instance =& $this;
}
 
public static function &get_instance()
{
        return self::$instance;
}
复制代码

helper是函数所以得用$CI = & get_instance();的方式去用系统加载的类
那么libraries目录下,我们写的类
是像控制器一样去继承CI_Controller类呢,
还是用get_instance()这个方法去实现 呢?
都一样吧??/???....... 呵呵

评分

参与人数 1威望 +5 收起 理由
Hex + 5 很给力!

查看全部评分

发表于 2012-2-1 11:07:18 | 显示全部楼层
写得不错啊。。楼主研究得很透彻。值得学习。

本版积分规则