文档是前提,没有捷径。 http://codeigniter.org.cn/user_guide/index.html
一、源码
代码语言:javascript复制// ..system/core/Common.php
if ( ! function_exists('load_class'))
{
/**
* Class registry
*
* This function acts as a singleton. If the requested class does not
* exist it is instantiated and set to a static variable. If it has
* previously been instantiated the variable is returned.
*
* @param string the class name being requested
* @param string the directory where the class should be found
* @param string an optional argument to pass to the class constructor
* @return object
*/
function &load_class($class, $directory = 'libraries', $param = NULL)
{
static $_classes = array();
// Does the class exist? If so, we're done...
if (isset($_classes[$class]))
{
return $_classes[$class];
}
$name = FALSE;
// Look for the class first in the local application/libraries folder
// then in the native system/libraries folder
foreach (array(APPPATH, BASEPATH) as $path)
{
if (file_exists($path.$directory.'/'.$class.'.php'))
{
$name = 'CI_'.$class;
if (class_exists($name, FALSE) === FALSE)
{
require_once($path.$directory.'/'.$class.'.php');
}
break;
}
}
// Is the request a class extension? If so we load it too
if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
{
$name = config_item('subclass_prefix').$class;
if (class_exists($name, FALSE) === FALSE)
{
require_once(APPPATH.$directory.'/'.$name.'.php');
}
}
// Did we find the class?
if ($name === FALSE)
{
// Note: We use exit() rather than show_error() in order to avoid a
// self-referencing loop with the Exceptions class
set_status_header(503);
echo 'Unable to locate the specified class: '.$class.'.php';
exit(5); // EXIT_UNK_CLASS
}
// Keep track of what we just loaded
is_loaded($class);
$_classes[$class] = isset($param)
? new $name($param)
: new $name();
return $_classes[$class];
}
}
先找个调用的例子吧。
代码语言:javascript复制$CFG =& load_class('Config', 'core');
此处是“加载”了配置类。
二、源码分析
1. “&”符号
$CFG =& load_class('Config', 'core');
其中: 比较重要的是 “&”符号,定义函数和调用函数时,均有使用。在此处是获得返回对象的引用。
2. “function_exists”
一般加载公共函数时使用,判断当前环境是否存在该函数。以判断是否需要继续加载
3. 代码片段
代码语言:javascript复制// Look for the class first in the local application/libraries folder
// then in the native system/libraries folder
// APPPATH 为CI的application文件夹绝对地址(文件夹名称可修改,在index.php中。详细参见文档。)
// BASEPATH 为CI的system文件夹绝对地址
foreach (array(APPPATH, BASEPATH) as $path)
{
if (file_exists($path.$directory.'/'.$class.'.php'))
{
// CI框架自己的类使用了"CI_"前缀
$name = 'CI_'.$class;
// 判断当前环境中是否存在该类,参数$autoload=FALSE 不自动加载
if (class_exists($name, FALSE) === FALSE)
{
// 加载该文件
require_once($path.$directory.'/'.$class.'.php');
}
break;
}
}
代码语言:javascript复制// Is the request a class extension? If so we load it too
// 是否是请求加载一个类扩展?如果是 我们也同样加载它
// 判断在 ..application/xxx 文件夹下面是否存在这个文件
// subclass_prefix 配置见 下面的代码段
if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
{
$name = config_item('subclass_prefix').$class;
if (class_exists($name, FALSE) === FALSE)
{
require_once(APPPATH.$directory.'/'.$name.'.php');
}
}
//-------------------- ..config/config.php
/*
|--------------------------------------------------------------------------
| Class Extension Prefix
|--------------------------------------------------------------------------
|
| This item allows you to set the filename/classname prefix when extending
| native libraries. For more information please see the user guide:
|
| https://codeigniter.com/user_guide/general/core_classes.html
| https://codeigniter.com/user_guide/general/creating_libraries.html
|
*/
// 当你扩展本地库时,这一项允许你设置前缀。 比如: class MY_Config
$config['subclass_prefix'] = 'MY_';
代码语言:javascript复制// 这块为加载完类之后, 返回一个对象。
// 由于函数定义及引用时,使用了“&” 此处创建的对象,也就等同于调用该函数时得到的返回对象。
$_classes[$class] = isset($param)? new $name($param) : new $name();
//------------------------字符串变量创建对象
class XX {}
$class_name = 'XX';
$class = new $class_name(); // 即可创建对象
三、精简示例
代码语言:javascript复制// 假设存在这么一个 "XX.php"文件,里面包含一个 "X_XX"类
function &load_xx() {
require_once 'XX.php';
$name = 'X__XX';
$entry = new $name();
return $entry;
}
// $x 即为函数创建的类对象引用
$x =& load_xx();