ci源码分析--libraries/loader
<?phpif ( ! defined('BASEPATH')) exit('不允许直接访问');
/**
* CodeIgniter
*
* An open source application development framework for PHP 4.3.2 or newer
*
* @packageCodeIgniter
* @authorExpressionEngine Dev Team
* @copyright Copyright (c) 2008, EllisLab, Inc.
* @licensehttp://codeigniter.com/user_guide/license.html
* @linkhttp://codeigniter.com
* @sinceVersion 1.0
* @filesource
*/
// ------------------------------------------------------------------------
/**
* Loader Class
*
* Loads views and files
*
* @packageCodeIgniter
* @subpackage Libraries
* @authorExpressionEngine Dev Team
* @修改 icebolt(29142986)
* @category Loader
* @linkhttp://codeigniter.com/user_guide/libraries/loader.html
*/
class CI_Loader {
var $_ci_ob_level;
var $_ci_view_path= '';
var $_ci_is_php5= FALSE;
var $_ci_is_instance= FALSE;
var $_ci_cached_vars = array();
var $_ci_classes= array();
var $_ci_loaded_files = array();
var $_ci_models = array();
var $_ci_helpers= array();
var $_ci_plugins= array();
var $_ci_varmap = array('unit_test' => 'unit', 'user_agent' => 'agent');
function CI_Loader()
{
$this->_ci_is_php5 = (floor(phpversion()) >= 5) ? TRUE : FALSE;
$this->_ci_view_path = APPPATH.'views/';
$this->_ci_ob_level= ob_get_level();
log_message('debug', "Loader类初始化成功");
}
//这个函数是用来加载核心类。
function library($library = '', $params = NULL, $object_name = NULL)
{
//第一个参数不能为空
if ($library == '')
{
return FALSE;
}
//第二个参数必须是一个数组,否则为空
if ( ! is_null($params) AND ! is_array($params))
{
$params = NULL;
}
if (is_array($library))
{
foreach ($library as $class)
{
$this->_ci_load_class($class, $params, $object_name);
}
}
else
{
$this->_ci_load_class($library, $params, $object_name);
}
$this->_ci_assign_to_models();
}
//载入模块
function model($model, $name = '', $db_conn = FALSE)
{
if (is_array($model))
{
foreach($model as $babe)
{
$this->model($babe);
}
return;
}
if ($model == '')
{
return;
}
if (strpos($model, '/') === FALSE)
{
$path = '';
}
else
{
$x = explode('/', $model);
$model = end($x);
unset($x);
$path = implode('/', $x).'/';
}
if ($name == '')
{
$name = $model;
}
if (in_array($name, $this->_ci_models, TRUE))
{
return;
}
$CI =& get_instance();
if (isset($CI->$name))
{
show_error('模块名已经被占用: '.$name);
}
$model = strtolower($model);
if ( ! file_exists(APPPATH.'models/'.$path.$model.EXT))
{
show_error('找不到模块文件: '.$model);
}
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('Model'))
{
load_class('Model', FALSE);
}
require_once(APPPATH.'models/'.$path.$model.EXT);
$model = ucfirst($model);
$CI->$name = new $model();
$CI->$name->_assign_libraries();
$this->_ci_models[] = $name;
}
//载入数据库连接
function database($params = '', $return = FALSE, $active_record = FALSE)
{
$CI =& get_instance();
if (class_exists('CI_DB') AND $return == FALSE AND $active_record == FALSE AND isset($CI->db) AND is_object($CI->db))
{
return FALSE;
}
require_once(BASEPATH.'database/DB'.EXT);
if ($return === TRUE)
{
return DB($params, $active_record);
}
$CI->db = '';
$CI->db =& DB($params, $active_record);
$this->_ci_assign_to_models();
}
//载入数据库工具类
function dbutil()
{
if ( ! class_exists('CI_DB'))
{
$this->database();
}
$CI =& get_instance();
$CI->load->dbforge();
require_once(BASEPATH.'database/DB_utility'.EXT);
require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility'.EXT);
$class = 'CI_DB_'.$CI->db->dbdriver.'_utility';
$CI->dbutil =& new $class();
$CI->load->_ci_assign_to_models();
}
//载入数据库工厂类
function dbforge()
{
if ( ! class_exists('CI_DB'))
{
$this->database();
}
$CI =& get_instance();
require_once(BASEPATH.'database/DB_forge'.EXT);
require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT);
$class = 'CI_DB_'.$CI->db->dbdriver.'_forge';
$CI->dbforge = new $class();
$CI->load->_ci_assign_to_models();
}
//载入视图
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));
}
//载入一个文件
function file($path, $return = FALSE)
{
return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
}
//让视图可以直接调用控制器的变量
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;
}
}
}
//载入助手类
function helper($helpers = array())
{
if ( ! is_array($helpers))
{
$helpers = array($helpers);
}
foreach ($helpers as $helper)
{
$helper = strtolower(str_replace(EXT, '', str_replace('_helper', '', $helper)).'_helper');
if (isset($this->_ci_helpers[$helper]))
{
continue;
}
$ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.EXT;
if (file_exists($ext_helper))
{
$base_helper = BASEPATH.'helpers/'.$helper.EXT;
if ( ! file_exists($base_helper))
{
show_error('不能载入需要的文件: helpers/'.$helper.EXT);
}
include_once($ext_helper);
include_once($base_helper);
}
elseif (file_exists(APPPATH.'helpers/'.$helper.EXT))
{
include_once(APPPATH.'helpers/'.$helper.EXT);
}
else
{
if (file_exists(BASEPATH.'helpers/'.$helper.EXT))
{
include_once(BASEPATH.'helpers/'.$helper.EXT);
}
else
{
show_error('不能载入需要的文件: helpers/'.$helper.EXT);
}
}
$this->_ci_helpers[$helper] = TRUE;
log_message('debug', '载入助手类: '.$helper);
}
}
//载入助手类的别名
function helpers($helpers = array())
{
$this->helper($helpers);
}
//载入插件
function plugin($plugins = array())
{
if ( ! is_array($plugins))
{
$plugins = array($plugins);
}
foreach ($plugins as $plugin)
{
$plugin = strtolower(str_replace(EXT, '', str_replace('_pi', '', $plugin)).'_pi');
if (isset($this->_ci_plugins[$plugin]))
{
continue;
}
if (file_exists(APPPATH.'plugins/'.$plugin.EXT))
{
include_once(APPPATH.'plugins/'.$plugin.EXT);
}
else
{
if (file_exists(BASEPATH.'plugins/'.$plugin.EXT))
{
include_once(BASEPATH.'plugins/'.$plugin.EXT);
}
else
{
show_error('不能载入需要的文件: plugins/'.$plugin.EXT);
}
}
$this->_ci_plugins[$plugin] = TRUE;
log_message('debug', '载入插件: '.$plugin);
}
}
//载入插件的别名
function plugins($plugins = array())
{
$this->plugin($plugins);
}
//载入语言文件
function language($file = array(), $lang = '')
{
$CI =& get_instance();
if ( ! is_array($file))
{
$file = array($file);
}
foreach ($file as $langfile)
{
$CI->lang->load($langfile, $lang);
}
}
//载入脚手架的语言文件,没多大用,可以替换掉
function scaffold_language($file = '', $lang = '', $return = FALSE)
{
$CI =& get_instance();
return $CI->lang->load($file, $lang, $return);
}
//载入配置文件
function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
{
$CI =& get_instance();
$CI->config->load($file, $use_sections, $fail_gracefully);
}
//开启脚手架功能
function scaffolding($table = '')
{
if ($table === FALSE)
{
show_error('必须输入一个你要控制的数据库表');
}
$CI =& get_instance();
$CI->_ci_scaffolding = TRUE;
$CI->_ci_scaff_table = $table;
}
//载入器,用于载入视图和文件等
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];
}
// Set the path to the requested file
if ($_ci_path == '')
{
$_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
$_ci_file = ($_ci_ext == '') ? $_ci_view.EXT : $_ci_view;
$_ci_path = $this->_ci_view_path.$_ci_file;
}
else
{
$_ci_x = explode('/', $_ci_path);
$_ci_file = end($_ci_x);
}
if ( ! file_exists($_ci_path))
{
show_error('Unable to load the requested file: '.$_ci_file);
}
// This allows anything loaded using $this->load (views, files, etc.)
// to become accessible from within the Controller and Model functions.
// Only needed when running PHP 5
if ($this->_ci_is_instance())
{
$_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);
/*
* Buffer the output
*
* We buffer the output for two reasons:
* 1. Speed. You get a significant speed boost.
* 2. So that the final rendered template can be
* post-processed by the output class.Why do we
* need post processing?For one thing, in order to
* show the elapsed page load time.Unless we
* can intercept the content right before it's sent to
* the browser and then stop the timer it won't be accurate.
*/
ob_start();
// If the PHP installation does not support short tags we'll
// do a little string replacement, changing the short tags
// to standard PHP echo statements.
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', '载入文件: '.$_ci_path);
// Return the file data if requested
if ($_ci_return === TRUE)
{
$buffer = ob_get_contents();
@ob_end_clean();
return $buffer;
}
if (ob_get_level() > $this->_ci_ob_level + 1)
{
ob_end_flush();
}
else
{
global $OUT;
$OUT->append_output(ob_get_contents());
@ob_end_clean();
}
}
//私有函数,载入类
function _ci_load_class($class, $params = NULL, $object_name = NULL)
{
//去除扩展名和前后的/
$class = str_replace(EXT, '', trim($class, '/'));
$subdir = '';
if (strpos($class, '/') !== FALSE)
{
//用‘/’分解字符串
$x = explode('/', $class);
//获取最后元素一个为类名
$class = end($x);
//删除这个元素
unset($x);
//获得类名的目录
$subdir = implode($x, '/').'/';
}
//最小化全部字符,大写第一个字母,两种方法进行载入
foreach (array(ucfirst($class), strtolower($class)) as $class)
{
//继承类文件路径
$subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.EXT;
//继承类文件是否存在
if (file_exists($subclass))
{
//主类文件是否存在
$baseclass = BASEPATH.'libraries/'.ucfirst($class).EXT;
if ( ! file_exists($baseclass))
{
log_message('error', "不能载入类: ".$class);
show_error("不能载入类: ".$class);
}
//继承类是否已经载入
if (in_array($subclass, $this->_ci_loaded_files))
{
//是否用另外一个名字声明类
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."已经载入.");
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;
//分别通过 APPPATH BASEPATH两个目录尝试载入类文件
for ($i = 1; $i < 3; $i++)
{
//分别通过 APPPATH BASEPATH两个目录尝试载入类文件
$path = ($i % 2) ? APPPATH : BASEPATH;
$filepath = $path.'libraries/'.$subdir.$class.EXT;
//文件是否存在
if ( ! file_exists($filepath))
{
continue;
}
//类是否已经载入
if (in_array($filepath, $this->_ci_loaded_files))
{
//是否用另外一个名字声明类
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."已经载入.");
return;
}
include_once($filepath);
$this->_ci_loaded_files[] = $filepath;
return $this->_ci_init_class($class, '', $params, $object_name);
}
}
// One last attempt.Maybe the library is in a subdirectory, but it wasn't specified?
//不知道这块有什么作用,没多大用,估计是考虑使用者没有输入类名,只输入了路径名,有时间测试一下看看,不过不会有这么弱智的使用者吧
if ($subdir == '')
{
$path = strtolower($class).'/'.$class;
return $this->_ci_load_class($path, $params);
}
//不能载入重复的类
if ($is_duplicate == FALSE)
{
log_message('error', "不能载入重复的类: ".$class);
show_error("不能载入重复的类: ".$class);
}
}
//私有函数,初始化类
function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)
{
//配置参数为空,尝试载入config里面有没有配置文件
if ($config === NULL)
{
if (file_exists(APPPATH.'config/'.strtolower($class).EXT))
{
include_once(APPPATH.'config/'.strtolower($class).EXT);
}
else
{
if (file_exists(APPPATH.'config/'.ucfirst(strtolower($class)).EXT))
{
include_once(APPPATH.'config/'.ucfirst(strtolower($class)).EXT);
}
}
}
//类前缀为空
if ($prefix == '')
{
if (class_exists('CI_'.$class))
{
$name = 'CI_'.$class;
}
elseif (class_exists(config_item('subclass_prefix').$class))
{
$name = config_item('subclass_prefix').$class;
}
else
{
$name = $class;
}
}
else
{
$name = $prefix.$class;
}
//是否已经载入过这个类
if ( ! class_exists($name))
{
log_message('error', "指定类不存在: ".$name);
show_error("指定类不存在: ".$class);
}
$class = strtolower($class);
if (is_null($object_name))
{
$classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class];
}
else
{
$classvar = $object_name;
}
//记住载入的类名
$this->_ci_classes[$class] = $classvar;
//实例化类
$CI =& get_instance();
if ($config !== NULL)
{
$CI->$classvar = new $name($config);
}
else
{
$CI->$classvar = new $name;
}
}
//自动载入类、助手类,插架,语言等
function _ci_autoloader()
{
//载入自动载入配置文件
include_once(APPPATH.'config/autoload'.EXT);
//如果配置文件为空,直接返回
if ( ! isset($autoload))
{
return FALSE;
}
// 载入配置项
if (count($autoload['config']) > 0)
{
$CI =& get_instance();
foreach ($autoload['config'] as $key => $val)
{
$CI->config->load($val);
}
}
//通过循环载入helper、plugin、language
foreach (array('helper', 'plugin', 'language') as $type)
{
if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
{
$this->$type($autoload[$type]);
}
}
// A little tweak to remain backward compatible
// The $autoload['core'] item was deprecated
if ( ! isset($autoload['libraries']))
{
$autoload['libraries'] = $autoload['core'];
}
// Load libraries
if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
{
// Load the database driver.
if (in_array('database', $autoload['libraries']))
{
$this->database();
$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
}
// Load scaffolding
if (in_array('scaffolding', $autoload['libraries']))
{
$this->scaffolding();
$autoload['libraries'] = array_diff($autoload['libraries'], array('scaffolding'));
}
// Load all other libraries
foreach ($autoload['libraries'] as $item)
{
$this->library($item);
}
}
// Autoload models
if (isset($autoload['model']))
{
$this->model($autoload['model']);
}
}
//
function _ci_assign_to_models()
{
if (count($this->_ci_models) == 0)
{
return;
}
if ($this->_ci_is_instance())
{
$CI =& get_instance();
foreach ($this->_ci_models as $model)
{
$CI->$model->_assign_libraries();
}
}
else
{
foreach ($this->_ci_models as $model)
{
$this->$model->_assign_libraries();
}
}
}
//对象转化成数组
function _ci_object_to_array($object)
{
return (is_object($object)) ? get_object_vars($object) : $object;
}
//
function _ci_is_instance()
{
if ($this->_ci_is_php5 == TRUE)
{
return TRUE;
}
global $CI;
return (is_object($CI)) ? TRUE : FALSE;
}
}
ci的真正的核心的核心,希望大家能对这个文件仔细掌握,因为ci的大部分的mvc是在这里实现的 php函数提示
extract
这个函数在这里有用到,有的可能不太熟悉,这个是把数组的分解
比如
$test_arr=array("aaa"=>"bbb");
extract($test_arr)
就相当于
$aaa="bbb";
有什么问题,希望大家即时交流 顶一个。 下载了ci的最新版本,重新修改了一下 我帮楼主修正了一下语法高亮,呵呵 楼主辛苦了,不过只是些注释的简单翻译,希望楼主能写点分析Why的文章。支持 没感觉分析了多少 楼主辛苦了,不过只是些注释的简单翻译,希望楼主能写点分析Why的文章。支持 ...
recolee 发表于 2009-3-12 17:31 http://codeigniter.org.cn/forums/images/common/back.gif
说的好!
why?how?都没怎么讲
页:
[1]