专栏首页若是烟花CodeIgniter (CI) 框架学习 -- load_class

CodeIgniter (CI) 框架学习 -- load_class

文档是前提,没有捷径。 http://codeigniter.org.cn/user_guide/index.html


一、源码

// ..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];
	}
}

先找个调用的例子吧。

$CFG =& load_class('Config', 'core');

此处是“加载”了配置类。

二、源码分析

1. “&”符号

$CFG =& load_class('Config', 'core');

其中: 比较重要的是 “&”符号,定义函数和调用函数时,均有使用。在此处是获得返回对象的引用。

2. “function_exists”

一般加载公共函数时使用,判断当前环境是否存在该函数。以判断是否需要继续加载

3. 代码片段

// 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;
	}
}
// 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_';
// 这块为加载完类之后, 返回一个对象。 
// 由于函数定义及引用时,使用了“&” 此处创建的对象,也就等同于调用该函数时得到的返回对象。
$_classes[$class] = isset($param)? new $name($param) : new $name();


//------------------------字符串变量创建对象

class XX {}

$class_name = 'XX';

$class = new $class_name(); // 即可创建对象

三、精简示例

// 假设存在这么一个 "XX.php"文件,里面包含一个 "X_XX"类
function &load_xx() {
    require_once 'XX.php';
    $name = 'X__XX';
    $entry = new $name();
    return $entry;
}

// $x 即为函数创建的类对象引用
$x =& load_xx();

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 传智播客OA项目学习--阶段二(实体设计及技巧)

    二、Hibernate映射(由于之前只看过MyBatis没看过Hibernate,所以写的比较啰嗦)

    lpe234
  • Solr基本搭建及MySQL配置

    启动后访问 http://127.0.0.1:8983/, 理论上即可进入Solr管理界面。具体内容见Solr Admin UI

    lpe234
  • linux shell 监控脚本 及 邮件发送

    起因: 公司部署的web服务经常莫名其妙的挂掉。而且 还找不到具体的问题,使用supervisor守护的gunicorn,但是在多次尝试重启失败之后, 就再也不...

    lpe234
  • JVM的简单实现

    felix
  • 专治不会看源码的毛病--spring源码解析AOP篇

    静儿
  • Spring 工具类之基本元素判断

    实际业务开发中偶尔会遇到判断一个对象是否为基本数据类型,除了我们自老老实实的自己写之外,也可以借助 Spring 的 BeanUtils 工具类来实现

    一灰灰blog
  • Spring 工具类之基本元素判断

    实际业务开发中偶尔会遇到判断一个对象是否为基本数据类型,除了我们自老老实实的自己写之外,也可以借助 Spring 的 BeanUtils 工具类来实现

    一灰灰blog
  • Spring是如何启用aop切面

    首先从后面说实现原理,通过aop包下的AspectJAwareAdvisorAutoProxyCreator 继承自AbstractAdvisorAutoPro...

    一滴水的眼泪
  • Java类加载器详解(下)

    这个类中定义了一个加密和解密的算法,很简单的,就是将字节和oxff异或一下即可,而且这个算法是加密和解密的都可以用,很是神奇呀!

    Java团长
  • python记录day_20 多继承

    在python中,支持多继承,一个类可以拥有多个父类。但是多继承中, 存在着这样一个问题,当两个父类中出现了重名方法的时候该怎么办呢? 这时就涉及到如何查找父类...

    py3study

扫码关注云+社区

领取腾讯云代金券