在了解spl_autoload_register()函数之前,先来看另一个函数:__autoload。
一、__autoload
这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数。看下面例子:
printit.class.php
class PRINTIT {
function doPrint() {
echo 'hello world';
}
}
?>
index.php
例1
function__autoload( $class ) {
$file = $class . '.class.php';
if ( is_file($file) ) {
require_once($file);
}
}
$obj = newPRINTIT();
$obj->doPrint();
?>
运行index.php后正常输出hello world。在index.php中,由于没有包含printit.class.php,在实例化printit时,自动调用__autoload函数,参数$class的值即为类名printit,此时printit.class.php就被引进来了。
在面向对象中这种方法经常使用,可以避免书写过多的引用文件,同时也使整个系统更加灵活。
例2(调用不同目录的类)
function__autoload($_ClassName){
if(substr($_ClassName,-6)=='Action'){
requireROOT_PATH.'/action/'.$_ClassName.'.class.php';
}elseif(substr($_ClassName,-5)=='Model'){
requireROOT_PATH.'/model/'.$_ClassName.'.class.php';
}else{
requireROOT_PATH.'/includes/'.$_ClassName.'.class.php';
}
}
?>
注释:
ROOT_PATH:为定义的根目录常量
action目录存放控制类,model目录存放模型类,includes存放其他类
类名严格定义,诸如class IndexAction{}、class ManageModel{}、class Tool{}等
二、spl_autoload_register()
再看spl_autoload_register(),这个函数与__autoload有与曲同工之妙,看个简单的例子:
例1:
functionloadprint( $class ) {
$file = $class . '.class.php';
if (is_file($file)) {
require_once($file);
}
}
spl_autoload_register('loadprint' );
$obj = newPRINTIT();
$obj->doPrint();
?>
将__autoload换成loadprint函数。但是loadprint不会像__autoload自动触发,这时spl_autoload_register()就起作用了,它告诉PHP碰到没有定义的类就执行loadprint()。
spl_autoload_register()调用静态方法
class test {
public static function loadprint( $class ) {
$file = $class . '.class.php';
if (is_file($file)) {
require_once($file);
}
}
}
spl_autoload_register( array('test','loadprint') );
//另一种写法:spl_autoload_register( "test::loadprint" );
$obj = newPRINTIT();
$obj->doPrint();
?>
例2:(调用不同目录的类)
define('PATH_ROOT',realpath(dirname(__FILE__))); //根目录
define('DS',DIRECTORY_SEPARATOR);//路径分割 win下\ linux下/
define('PATH_CLASS',PATH_ROOT.DS.'includes/class/');
define('PATH_MODEL',PATH_ROOT.DS.'includes/model/');
define('PATH_CONTROL',PATH_ROOT.DS.'includes/control/');
spl_autoload_register("cms_autoload_class");
functioncms_autoload_class($str_className) {
$_arr_class= explode("_", strtolower($str_className));
print_r($_arr_class );
switch ($_arr_class[0]) {
case "class":
require(PATH_CLASS . $_arr_class[1]. ".class.php");
break;
case "model":
if (isset($_arr_class[2])&& !fn_isEmpty($_arr_class[2])) {
//fn_isEmpty函数最后会解释
require(PATH_MODEL .$_arr_class[1] . "_" . $_arr_class[2] . ".class.php");
} else {
require(PATH_MODEL .$_arr_class[1] . ".class.php");
}
break;
case "control":
if (isset($_arr_class[3])&& !fn_isEmpty($_arr_class[3])) {
require(PATH_CONTROL .$_arr_class[1] . DS . $_arr_class[2] . DS . $_arr_class[3] .".class.php");
} else {
require(PATH_CONTROL .$_arr_class[1] . DS . $_arr_class[2] . ".class.php");
}
break;
}
}
比如控制类文件的存放目录为includes/control/setup/update.class.php
update.class.php文件中的类名为 CONTROL_SETUP_UPDATE;
不难看出,类名CONTROL_SETUP_UPDATE与目录名和类文件名的.class前缀保持一致
利用$_arr_class = explode("_",strtolower($str_className));对类名参数$str_className进行分割,得到数组$_arr_class =Array ( [0] => control, [1] =>setup, [2] => update ),分割成的数组元素恰好就是目录名以及类文件名.class的前缀,然后对数组元素进行判断,若条件成立则required类文件。
若想向纵深一级的目录进行延伸,比如类文件的存放目录为:
includes/control/setup/manage/update.class.php那么类名为CONTROL_SETUP_MANAGE_UPDATE
分割的数组$_arr_class =Array ( [0] => control, [1] =>setup, [2] => manage, [3] => update)
若想向根目录下的五级目录进行延伸,则需要修改程序,得到$_arr_class[4]进行条件判断。
知识扩展:fn_isEmpty()函数
PHP中判断变量为空的几种方法小结
1. isset功能:判断变量是否被初始化
说明:它并不会判断变量是否为空,并且可以用来判断数组中元素是否被定义过
if (!isset($b))echo '$b 未被初始化' . "";
2. empty功能:检测变量是否为"空"
说明:任何一个未初始化的变量、值为 0 或 false 或 空字符串"" 或 null的变量、空数组、没有任何属性的对象,都将判断为empty==true
注意1:未初始化的变量也能被empty检测为"空"
functionfn_isEmpty($data) {
if (!isset($data)) {
returntrue;
}
if ($data === null) {
return true;
}
if (is_array($data) ||is_object($data)) {
if(empty($data)) {
returntrue;
}
} else {
if(empty($data) || trim($data) === "") {
returntrue;
}
}
return false;
}