在CI框架的声明中多次利用静态变量,来实现单利模式,首先来理解一下&符号的作用:
<?php
function &test() //定义函数时,函数名前必须加上&符号才能有效
{
static $b=0;
$b++;
return $b;
}
$a = &test(); //函数引用返回值 改变$a的值,也同时改变了$b 的值
echo test(); //此时为1
echo '<br>';
echo test(); //此时为2
echo '<br>';
$a = 100; //由于与$b指向同一地址,$a变为100,$b也会同时改变
echo test(); //此时为101
$a=test() 方式调用函数,只是将函数的值赋给$a而已, 而$a做任何改变 都不会影响到函数中的$b.
而通过$a=&test()方式调用函数呢, 它的作用是将return $b中的 $b变量的内存地址与$a变量的内存地址指向了同一个地方. 即产生了相当于这样的效果($a=&b;) 所以改变$a的值,也同时改变了$b 的值
在CI框架中index.php作为入口文件,在此设置了开发环境,此时设置的开发环境决定了以后加载的config参数,并且配置了一些基础路径,其中比较重要的两个路径分别是:
$system_path = 'system';
$application_folder = 'application';
define('BASEPATH', str_replace("\\", "/", $system_path));
define('APPPATH', $application_folder.'/');
然后引入CodeIgniter.php,其中CodeIgniter.php又分别引入了common.php和controller.php,便于理解,做个比喻,将ci框架比作一个将要建造的楼房,index文件就是这座楼房的入口,然后我要建造一个房间,我需要将这个房间的结构先想清楚,我的这个房间需要有厨房,大厅,卫生间等等,CodeIgniter.php就是这个房间的结构,大厅等就是我们需要加载的类,我们的大脑中有了这个房间的雏形,那我们应该怎么建造呢,我们需要一些工具,比如打桩机、搅拌机等等,在我们CI中充当工具的就是common.php这个文件,有了以上我们就可以建造我们的房间了,建造出来的房间就是controller.php中定义的CI_Controller.
CodeIgniter.php的主要作用是加载CI需要的一些组件,并且同过下面这个函数来返回一个CI_Controller的一个实例
require BASEPATH.'core/Controller.php';
function &get_instance()
{
return CI_Controller::get_instance();
}
讲Common.php中的加载函数之前要先说一下用户的自定义类:用户自定义的类有两种,一种是用自定义的类替换掉原始类:例如,要替换原始的 Email 类库。你必须创建一个文件application/libraries/Email.php, 并按如下方式声明类:
class CI_Email{
}
另一种是扩展现有类:
如果你需要在现有类库中加入一两个新的功能,那就完全不必要替换整个类库文件.你只需简单地扩展(继承)现有的类,扩展一个类就像在类中增加一些例外:
1. 扩展的类必须申明由父类扩展而来.
2. 新扩展的类所在的文件必须以 MY_ 为前缀(这个选项是在config.php中配置的,可以自定义)。
例如,要扩展原始类 Email 类你要建立文件 application/libraries/MY_Email.php, 并按如下方式在文件中声明:
class MY_Email extends CI_Email {
}
common.php中的加载函数:
if ( ! function_exists('load_class'))
{
function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
{
static $_classes = array();//通过静态数组,使已经加载的类不在被加载
if (isset($_classes[$class]))
{
return $_classes[$class];
}
$name = FALSE;
//通过foreach循环来优先加载用户自定义的类,上面讲过
foreach (array(APPPATH, BASEPATH) as $path)
{
if (file_exists($path.$directory.'/'.$class.'.php'))
{
$name = $prefix.$class;
if (class_exists($name) === FALSE)
{
require($path.$directory.'/'.$class.'.php');
}
break;
}
}
//加载用户定义的扩展类,通过config_item()函数获得配置文件中类前缀名
if(file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
{
$name = config_item('subclass_prefix').$class;
if (class_exists($name) === FALSE)
{
require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php');
}
}
// Did we find the class?
if ($name === FALSE)
{
// Note: We use exit() rather then show_error() in order to avoid a
// self-referencing loop with the Excptions class
exit('Unable to locate the specified class: '.$class.'.php');
}
//将已经加载的类通过此函数记录,供CI_Controller这个超级对象初始化时来加载这些类
is_loaded($class);
$_classes[$class] = new $name();
//返回这个加载的类的实例
return $_classes[$class];
}
}
common.php中和配置有关的两个函数分别是:
//此函数的作用总结来说就是初始化一些最基本的配置信息,从另一方面来说就是此时config类尚未加载,所以我们需要此全局函数来加载一些基本配置信息,以后的配置信息的操作将交由config类完成
if ( ! function_exists('get_config'))
{
function &get_config($replace = array())
{
static $_config;
if (isset($_config))
{
return $_config[0];
}
//如果没有定义自己的配置文件的话,默认使用APPPATH.'config/config.php'的配置文件
if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
{
$file_path = APPPATH.'config/config.php';
}
// Fetch the config file
if ( ! file_exists($file_path))
{
exit('The configuration file does not exist.');
}
require($file_path);
// Does the $config array exist in the file?
if ( ! isset($config) OR ! is_array($config))
{
exit('Your config file does not appear to be formatted correctly.');
}
//替换APPPATH.'config/config.php'中配置数组的的内容,实际上并不有真正替换,替换的层面仅仅只是在内存中。
if (count($replace) > 0)
{
foreach ($replace as $key => $val)
{
if (isset($config[$key]))
{
$config[$key] = $val;
}
}
}
//将 $_config[0]指向APPPATH.'config/config.php'下的配置数组的地址
return $_config[0] =& $config;
}
}
以及
//返回某个配置信息
if ( ! function_exists('config_item'))
{
function config_item($item)
{
static $_config_item = array();
if ( ! isset($_config_item[$item]))
{
$config =& get_config();
if ( ! isset($config[$item]))
{
return FALSE;
}
$_config_item[$item] = $config[$item];
}
return $_config_item[$item];
}
}