CodeIgniter3-基类加载|覆盖分析

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与 applicationsystem按照以下规则,即可替换任意基类:
    • 相同的目录结构。
    • 特定的类文件/类前缀命名规则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值