1 背景
- 背景
- CI3生命周期,index.php末尾require_once BASEPATH.‘core/CodeIgniter.php’,它加载system的基础类时,是通过load_class()进行的。
- 需要拓展、改变基础类的行为,CI3提供了MY_前缀的子类继承机制。
- Loader基础类并不使用load_class()。
- 目标:修改、拓展基础类的行为。
2 源码
- application、system结构:
- 源码:
/**
* @param string the class name being requested
* @param string the directory where the class should be found
* @param mixed 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;
// 基类分两种模式:[1] 完全重写基类 [2] 继承拓展基类
// 模式[1]执行完步骤1即可
// 模式[2]需执行步骤1、2,载入$class.php::CI_$class类、MY_$class.php::MY_$class类。
// 1.按顺序以application/、system/为根路径,寻找基类加载:
// 匹配 $directory 子目录路径;
// 匹配 $class.php 文件 -> 类名 $name = "CI_" . $class;
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;
}
}
// 2.配合模式[2],寻找继承类:
// 匹配 $directory 子目录路径;
// 匹配 MY_$class.php文件 -> 类名 $name = "MY_" . $class;
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
}
// 3.记录实例历史
is_loaded($class);
// 4.返回实例:
// 模式[1]:加载 $application/$directory/$class.php::CI_$class类;
// 模式[2]:加载 $application/$directory/MY_$class.php::MY_$class类、
// $system/$directory/$class.php::CI_$class类;
$_classes[$class] = isset($param)
? new $name($param)
: new $name();
return $_classes[$class];
}
// 判断是否实例化过:
// 无则记录
function &is_loaded($class = '')
{
static $_is_loaded = array();
if ($class !== '')
{
$_is_loaded[strtolower($class)] = $class;
}
return $_is_loaded;
}
- 依据上述加载过程,
a
p
p
l
i
c
a
t
i
o
n
与
application与
application与system按照以下规则,即可替换任意基类:
- 相同的目录结构。
- 特定的类文件/类前缀命名规则。