源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

CI框架装载器Loader.php源码分析

  • 时间:2022-02-11 00:10 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:CI框架装载器Loader.php源码分析
顾名思义,装载器就是加载元素的,使用CI时,经常加载的有: $this->load->library() $this->load->view() $this->load->model() $this->load->database() $this->load->helper() $this->load->config() $this->load->add_package_path()
[u]复制代码[/u] 代码如下:
/**  * Loader Class  *  * 用户加载views和files,常见的函数有model(),view(),library(),helper()  *  * Controller的好助手,$this->load =& load_class('Loader', 'core');,加载了loader,Controller就无比强大了  */ class CI_Loader {  protected $_ci_ob_level;  protected $_ci_view_paths  = array();  protected $_ci_library_paths = array();  protected $_ci_model_paths  = array();  protected $_ci_helper_paths  = array();  protected $_base_classes  = array(); // Set by the controller class  protected $_ci_cached_vars  = array();  protected $_ci_classes   = array();  protected $_ci_loaded_files  = array();    protected $_ci_models   = array();  protected $_ci_helpers   = array();  protected $_ci_varmap   = array('unit_test' => 'unit',            'user_agent' => 'agent');  public function __construct()  {                       //获取缓冲嵌套级别   $this->_ci_ob_level  = ob_get_level();   //library路径                 $this->_ci_library_paths = array(APPPATH, BASEPATH);                 //helper路径   $this->_ci_helper_paths = array(APPPATH, BASEPATH);                 //model路径   $this->_ci_model_paths = array(APPPATH);                 //view路径   $this->_ci_view_paths = array(APPPATH.'views/' => TRUE);   log_message('debug', "Loader Class Initialized");  }  // --------------------------------------------------------------------  /**   * 初始化Loader   *   */  public function initialize()  {   $this->_ci_classes = array();   $this->_ci_loaded_files = array();   $this->_ci_models = array();                 //将is_loaded(common中记录加载核心类函数)加载的核心类交给_base_classes   $this->_base_classes =& is_loaded();                 //加载autoload.php配置中文件   $this->_ci_autoloader();   return $this;  }  // --------------------------------------------------------------------  /**   * 检测类是否加载   */  public function is_loaded($class)  {   if (isset($this->_ci_classes[$class]))   {    return $this->_ci_classes[$class];   }   return FALSE;  }  // --------------------------------------------------------------------  /**   * 加载Class   */  public function library($library = '', $params = NULL, $object_name = NULL)  {   if (is_array($library))   {    foreach ($library as $class)    {     $this->library($class, $params);    }    return;   }                 //如果$library为空或者已经加载。。。   if ($library == '' OR isset($this->_base_classes[$library]))   {    return FALSE;   }   if ( ! is_null($params) && ! is_array($params))   {    $params = NULL;   }   $this->_ci_load_class($library, $params, $object_name);  }  // --------------------------------------------------------------------  /**   * 加载和实例化model   */  public function model($model, $name = '', $db_conn = FALSE)  {                 //CI支持数组加载多个model   if (is_array($model))   {    foreach ($model as $babe)    {     $this->model($babe);    }    return;   }   if ($model == '')   {    return;   }   $path = '';   // 是否存在子目录   if (($last_slash = strrpos($model, '/')) !== FALSE)   {    // The path is in front of the last slash    $path = substr($model, 0, $last_slash + 1);    // And the model name behind it    $model = substr($model, $last_slash + 1);   }   if ($name == '')   {    $name = $model;   }   if (in_array($name, $this->_ci_models, TRUE))   {    return;   }   $CI =& get_instance();   if (isset($CI->$name))   {    show_error('The model name you are loading is the name of a resource that is already being used: '.$name);   }   $model = strtolower($model); //model文件名全小写   foreach ($this->_ci_model_paths as $mod_path)   {    if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))    {     continue;    }    if ($db_conn !== FALSE AND ! class_exists('CI_DB'))    {     if ($db_conn === TRUE)     {      $db_conn = '';     }     $CI->load->database($db_conn, FALSE, TRUE);    }    if ( ! class_exists('CI_Model'))    {     load_class('Model', 'core');    }    require_once($mod_path.'models/'.$path.$model.'.php');    $model = ucfirst($model);    $CI->$name = new $model();                         //保存在Loader::_ci_models中,以后可以用它来判断某个model是否已经加载过。    $this->_ci_models[] = $name;    return;   }   // couldn't find the model   show_error('Unable to locate the model you have specified: '.$model);  }  // --------------------------------------------------------------------  /**   * 数据库Loader   */  public function database($params = '', $return = FALSE, $active_record = NULL)  {   // Grab the super object   $CI =& get_instance();   // 是否需要加载db   if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($CI->db) AND is_object($CI->db))   {    return FALSE;   }   require_once(BASEPATH.'database/DB.php');   if ($return === TRUE)   {    return DB($params, $active_record);   }   // Initialize the db variable.  Needed to prevent   // reference errors with some configurations   $CI->db = '';   // Load the DB class   $CI->db =& DB($params, $active_record);  }  // --------------------------------------------------------------------  /**   * 加载数据库工具类   */  public function dbutil()  {   if ( ! class_exists('CI_DB'))   {    $this->database();   }   $CI =& get_instance();   // for backwards compatibility, load dbforge so we can extend dbutils off it   // this use is deprecated and strongly discouraged   $CI->load->dbforge();   require_once(BASEPATH.'database/DB_utility.php');   require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility.php');   $class = 'CI_DB_'.$CI->db->dbdriver.'_utility';   $CI->dbutil = new $class();  }  // --------------------------------------------------------------------  /**   * Load the Database Forge Class   *   * @return string   */  public function dbforge()  {   if ( ! class_exists('CI_DB'))   {    $this->database();   }   $CI =& get_instance();   require_once(BASEPATH.'database/DB_forge.php');   require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge.php');   $class = 'CI_DB_'.$CI->db->dbdriver.'_forge';   $CI->dbforge = new $class();  }  // --------------------------------------------------------------------  /**   * 加载视图文件   */  public function view($view, $vars = array(), $return = FALSE)  {   return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));  }  // --------------------------------------------------------------------  /**   * 加载普通文件   */  public function file($path, $return = FALSE)  {   return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));  }  // --------------------------------------------------------------------  /**   * 设置变量   *   * Once variables are set they become available within   * the controller class and its "view" files.   *   */  public function vars($vars = array(), $val = '')  {   if ($val != '' AND is_string($vars))   {    $vars = array($vars => $val);   }   $vars = $this->_ci_object_to_array($vars);   if (is_array($vars) AND count($vars) > 0)   {    foreach ($vars as $key => $val)    {     $this->_ci_cached_vars[$key] = $val;    }   }  }  // --------------------------------------------------------------------  /**   * 检查并获取变量   */  public function get_var($key)  {   return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL;  }  // --------------------------------------------------------------------  /**   * 加载helper   */  public function helper($helpers = array())  {   foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper)   {    if (isset($this->_ci_helpers[$helper]))    {     continue;    }    $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.'.php';    // 如果是扩展helper的话    if (file_exists($ext_helper))    {     $base_helper = BASEPATH.'helpers/'.$helper.'.php';     if ( ! file_exists($base_helper))     {      show_error('Unable to load the requested file: helpers/'.$helper.'.php');     }     include_once($ext_helper);     include_once($base_helper);     $this->_ci_helpers[$helper] = TRUE;     log_message('debug', 'Helper loaded: '.$helper);     continue;    }    // 如果不是扩展helper,helper路径中加载helper    foreach ($this->_ci_helper_paths as $path)    {     if (file_exists($path.'helpers/'.$helper.'.php'))     {      include_once($path.'helpers/'.$helper.'.php');      $this->_ci_helpers[$helper] = TRUE;      log_message('debug', 'Helper loaded: '.$helper);      break;     }    }    // 如果该helper还没加载成功的话,说明加载helper失败    if ( ! isset($this->_ci_helpers[$helper]))    {     show_error('Unable to load the requested file: helpers/'.$helper.'.php');    }   }  }  // --------------------------------------------------------------------  /**   * 可以看到helpers调用也是上面的helper,只是helpers的别名而已   */  public function helpers($helpers = array())  {   $this->helper($helpers);  }  // --------------------------------------------------------------------  /**   * 加载language文件   */  public function language($file = array(), $lang = '')  {   $CI =& get_instance();   if ( ! is_array($file))   {    $file = array($file);   }   foreach ($file as $langfile)   {    $CI->lang->load($langfile, $lang);   }  }  // --------------------------------------------------------------------  /**   * 加载配置文件   */  public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)  {   $CI =& get_instance();   $CI->config->load($file, $use_sections, $fail_gracefully);  }  // --------------------------------------------------------------------  /**   * Driver   *   * 加载 driver library   */  public function driver($library = '', $params = NULL, $object_name = NULL)  {   if ( ! class_exists('CI_Driver_Library'))   {    // we aren't instantiating an object here, that'll be done by the Library itself    require BASEPATH.'libraries/Driver.php';   }   if ($library == '')   {    return FALSE;   }   // We can save the loader some time since Drivers will *always* be in a subfolder,   // and typically identically named to the library   if ( ! strpos($library, '/'))   {    $library = ucfirst($library).'/'.$library;   }   return $this->library($library, $params, $object_name);  }  // --------------------------------------------------------------------  /**   * 添加 Package 路径   *   * 把package路径添加到库,模型,助手,配置路径   */  public function add_package_path($path, $view_cascade=TRUE)  {   $path = rtrim($path, '/').'/';   array_unshift($this->_ci_library_paths, $path);   array_unshift($this->_ci_model_paths, $path);   array_unshift($this->_ci_helper_paths, $path);   $this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;   $config =& $this->_ci_get_component('config');   array_unshift($config->_config_paths, $path);  }  // --------------------------------------------------------------------  /**   * 获取Package Paths,默认不包含BASEPATH   */  public function get_package_paths($include_base = FALSE)  {   return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths;  }  // --------------------------------------------------------------------  /**   * 剔除Package Path   *   * Remove a path from the library, model, and helper path arrays if it exists   * If no path is provided, the most recently added path is removed.   *   */  public function remove_package_path($path = '', $remove_config_path = TRUE)  {   $config =& $this->_ci_get_component('config');   if ($path == '')   {    $void = array_shift($this->_ci_library_paths);    $void = array_shift($this->_ci_model_paths);    $void = array_shift($this->_ci_helper_paths);    $void = array_shift($this->_ci_view_paths);    $void = array_shift($config->_config_paths);   }   else   {    $path = rtrim($path, '/').'/';    foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)    {     if (($key = array_search($path, $this->{$var})) !== FALSE)     {      unset($this->{$var}[$key]);     }    }    if (isset($this->_ci_view_paths[$path.'views/']))    {     unset($this->_ci_view_paths[$path.'views/']);    }    if (($key = array_search($path, $config->_config_paths)) !== FALSE)    {     unset($config->_config_paths[$key]);    }   }   // 保证应用默认的路径依然存在   $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));   $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));   $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));   $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));   $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));  }  // --------------------------------------------------------------------  /**   * Loader   *   * This function is used to load views and files.   * Variables are prefixed with _ci_ to avoid symbol collision with   * variables made available to view files   *   * @param array   * @return void   */  protected function _ci_load($_ci_data)  {   // Set the default data variables   foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)   {    $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];   }   $file_exists = FALSE;                 //如果$_ci_path不为空,则说明当前要加载普通文件。Loader::file才会有path   if ($_ci_path != '')   {    $_ci_x = explode('/', $_ci_path);    $_ci_file = end($_ci_x);   }   else   {    $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);    $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view;    foreach ($this->_ci_view_paths as $view_file => $cascade)    {     if (file_exists($view_file.$_ci_file))     {      $_ci_path = $view_file.$_ci_file;      $file_exists = TRUE;      break;     }     if ( ! $cascade)     {      break;     }    }   }                 //view文件不存在则会报错   if ( ! $file_exists && ! file_exists($_ci_path))   {    show_error('Unable to load the requested file: '.$_ci_file);   }   // 把CI的所有属性都传递给loader,view中$this指的是loader   $_ci_CI =& get_instance();   foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)   {    if ( ! isset($this->$_ci_key))    {     $this->$_ci_key =& $_ci_CI->$_ci_key;    }   }   /*    * Extract and cache variables    *    * You can either set variables using the dedicated $this->load_vars()    * function or via the second parameter of this function. We'll merge    * the two types and cache them so that views that are embedded within    * other views can have access to these variables.    */   if (is_array($_ci_vars))   {    $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);   }   extract($this->_ci_cached_vars);   /*    * 将视图内容放到缓存区    *    */   ob_start();   // 支持短标签   if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)   {    echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));   }   else   {    include($_ci_path); // include() vs include_once() allows for multiple views with the same name   }   log_message('debug', 'File loaded: '.$_ci_path);   // 是否直接返回view数据   if ($_ci_return === TRUE)   {    $buffer = ob_get_contents();    @ob_end_clean();    return $buffer;   }   //当前这个视图文件是被另一个视图文件通过$this->view()方法引入,即视图文件嵌入视图文件   if (ob_get_level() > $this->_ci_ob_level + 1)   {    ob_end_flush();   }   else   {       ////把缓冲区的内容交给Output组件并清空关闭缓冲区。    $_ci_CI->output->append_output(ob_get_contents());    @ob_end_clean();   }  }  // --------------------------------------------------------------------  /**   * 加载类   */  protected function _ci_load_class($class, $params = NULL, $object_name = NULL)  {   // 去掉.php和两端的/获取的$class就是类名或目录名+类名   $class = str_replace('.php', '', trim($class, '/'));   // CI允许dir/filename方式   $subdir = '';   if (($last_slash = strrpos($class, '/')) !== FALSE)   {    // 目录    $subdir = substr($class, 0, $last_slash + 1);    // 文件名    $class = substr($class, $last_slash + 1);   }   // 允许加载的类名首字母大写或全小写   foreach (array(ucfirst($class), strtolower($class)) as $class)   {    $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';    // 是否是扩展类    if (file_exists($subclass))    {     $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';     if ( ! file_exists($baseclass))     {      log_message('error', "Unable to load the requested class: ".$class);      show_error("Unable to load the requested class: ".$class);     }     // Safety:  Was the class already loaded by a previous call?     if (in_array($subclass, $this->_ci_loaded_files))     {      // Before we deem this to be a duplicate request, let's see      // if a custom object name is being supplied.  If so, we'll      // return a new instance of the object      if ( ! is_null($object_name))      {       $CI =& get_instance();       if ( ! isset($CI->$object_name))       {        return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);       }      }      $is_duplicate = TRUE;      log_message('debug', $class." class already loaded. Second attempt ignored.");      return;     }     include_once($baseclass);     include_once($subclass);     $this->_ci_loaded_files[] = $subclass;                                 //实例化类     return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);    }    // 如果不是扩展,和上面类似    $is_duplicate = FALSE;    foreach ($this->_ci_library_paths as $path)    {     $filepath = $path.'libraries/'.$subdir.$class.'.php';     // Does the file exist?  No?  Bummer...     if ( ! file_exists($filepath))     {      continue;     }     // Safety:  Was the class already loaded by a previous call?     if (in_array($filepath, $this->_ci_loaded_files))     {      // Before we deem this to be a duplicate request, let's see      // if a custom object name is being supplied.  If so, we'll      // return a new instance of the object      if ( ! is_null($object_name))      {       $CI =& get_instance();       if ( ! isset($CI->$object_name))       {        return $this->_ci_init_class($class, '', $params, $object_name);       }      }      $is_duplicate = TRUE;      log_message('debug', $class." class already loaded. Second attempt ignored.");      return;     }     include_once($filepath);     $this->_ci_loaded_files[] = $filepath;     return $this->_ci_init_class($class, '', $params, $object_name);    }   } // END FOREACH   // 如果还没有找到该class,最后的尝试是该class会不会在同名的子目录下   if ($subdir == '')   {    $path = strtolower($class).'/'.$class;    return $this->_ci_load_class($path, $params);   }   // 加载失败,报错   if ($is_duplicate == FALSE)   {    log_message('error', "Unable to load the requested class: ".$class);    show_error("Unable to load the requested class: ".$class);   }  }  // --------------------------------------------------------------------  /**   * 实例化已经加载的类   */  protected function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)  {   // 是否有类的配置信息   if ($config === NULL)   {    // Fetch the config paths containing any package paths    $config_component = $this->_ci_get_component('config');    if (is_array($config_component->_config_paths))    {     // Break on the first found file, thus package files     // are not overridden by default paths     foreach ($config_component->_config_paths as $path)     {      // We test for both uppercase and lowercase, for servers that      // are case-sensitive with regard to file names. Check for environment      // first, global next      if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))      {       include($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');       break;      }      elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))      {       include($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');       break;      }      elseif (file_exists($path .'config/'.strtolower($class).'.php'))      {       include($path .'config/'.strtolower($class).'.php');       break;      }      elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).'.php'))      {       include($path .'config/'.ucfirst(strtolower($class)).'.php');       break;      }     }    }   }   if ($prefix == '')   {       //system下library    if (class_exists('CI_'.$class))    {     $name = 'CI_'.$class;    }    elseif (class_exists(config_item('subclass_prefix').$class))    {       //扩展library     $name = config_item('subclass_prefix').$class;    }    else    {     $name = $class;    }   }   else   {    $name = $prefix.$class;   }   // Is the class name valid?   if ( ! class_exists($name))   {    log_message('error', "Non-existent class: ".$name);    show_error("Non-existent class: ".$class);   }   // Set the variable name we will assign the class to   // Was a custom class name supplied?  If so we'll use it   $class = strtolower($class);   if (is_null($object_name))   {    $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];   }   else   {    $classvar = $object_name;   }   // Save the class name and object name   $this->_ci_classes[$class] = $classvar;   // 将初始化的类的实例给CI超级句柄   $CI =& get_instance();   if ($config !== NULL)   {    $CI->$classvar = new $name($config);   }   else   {    $CI->$classvar = new $name;   }  }  // --------------------------------------------------------------------  /**   * 自动加载器          *          * autoload.php配置的自动加载文件有:          *  | 1. Packages             | 2. Libraries             | 3. Helper files             | 4. Custom config files             | 5. Language files             | 6. Models   */  private function _ci_autoloader()  {   if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))   {    include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');   }   else   {    include(APPPATH.'config/autoload.php');   }   if ( ! isset($autoload))   {    return FALSE;   }   // 自动加载packages,也就是将package_path加入到library,model,helper,config   if (isset($autoload['packages']))   {    foreach ($autoload['packages'] as $package_path)    {     $this->add_package_path($package_path);    }   }   // 加载config文件   if (count($autoload['config']) > 0)   {    $CI =& get_instance();    foreach ($autoload['config'] as $key => $val)    {     $CI->config->load($val);    }   }   // 加载helper和language   foreach (array('helper', 'language') as $type)   {    if (isset($autoload[$type]) AND count($autoload[$type]) > 0)    {     $this->$type($autoload[$type]);    }   }   // 这个好像是为了兼容以前版本的   if ( ! isset($autoload['libraries']) AND isset($autoload['core']))   {    $autoload['libraries'] = $autoload['core'];   }   // 加载libraries   if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)   {    // 加载db    if (in_array('database', $autoload['libraries']))    {     $this->database();     $autoload['libraries'] = array_diff($autoload['libraries'], array('database'));    }    // 加载所有其他libraries    foreach ($autoload['libraries'] as $item)    {     $this->library($item);    }   }   // Autoload models   if (isset($autoload['model']))   {    $this->model($autoload['model']);   }  }  // --------------------------------------------------------------------  /**   * 返回由对象属性组成的关联数组   */  protected function _ci_object_to_array($object)  {   return (is_object($object)) ? get_object_vars($object) : $object;  }  // --------------------------------------------------------------------  /**   * 获取CI某个组件的实例   */  protected function &_ci_get_component($component)  {   $CI =& get_instance();   return $CI->$component;  }  // --------------------------------------------------------------------  /**   * 处理文件名,这个函数主要是返回正确文件名   */  protected function _ci_prep_filename($filename, $extension)  {   if ( ! is_array($filename))   {    return array(strtolower(str_replace('.php', '', str_replace($extension, '', $filename)).$extension));   }   else   {    foreach ($filename as $key => $val)    {     $filename[$key] = strtolower(str_replace('.php', '', str_replace($extension, '', $val)).$extension);    }    return $filename;   }  } }
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部