CodeIgniter (CI) 框架学习 -- load_class

2020-07-27 17:15:06 浏览数 (1)

文档是前提,没有捷径。 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();

0 人点赞