php spl_autoload_register 与命名空间

php spl_autoload_register 与命名空间

准备工作

开始工作

打开php官方文档:

spl autoload register — 注册给定的函数作为 __autoload 的实现

将函数注册到SPL __autoload函数队列中。如果该队列中的函数尚未激活,则激活它们。

如果在你的程序中已经实现了autoload()函数,它必须显式注册到autoload()队列中。因为 spl_autoload_register()函数会将Zend Engine中的__autoload()函数取代为spl_autoload()或spl_autoload_call()。

如果需要多条 autoload 函数,spl_autoload_register() 满足了此类需求。 它实际上创建了 autoload 函数的队列,按定义时的顺序逐个执行。相比之下, __autoload() 只可以定义一次。

我们实现一个自动加载类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
我们新建一个lib.php
class CommonLib{
public static function start(){
spl_autoload_register('Lib\CommonLib::autoLoad');
}
public static function autoLoad($className){
if(false !== strpos($className,'\\')){
$name=strstr($className,'\\',true);
if(in_array($name,array('db','cache'))){
$path='./frame';
}else{
$path=dirname($path);
}
}
$fileName= path.DIRECTORY_SEPARATOR. str_replace('\\', '/', $className) . '.php';
if(file_exists($fileName)){
$fileName= strtolower(str_replace("\\", "/", $fileName));
require_once $fileName;
}
}
}

在上面的代码中我们做了对命名空间的处理,我们知道当我们引用

1
2
3
4
5
6
namespace A
class Test1{
}
我们实例化Test1的时候
必须是new A\Test1();或者用use 引用 use A\Test 这样才可以是new Test1()

但是在spl autoload register加入了命名空间后,实际上是include或者require的是A\Test1.php。很显然这个文件是不存在的所以加上namespace后spl autoload register就不好用了

在这样的情况下我们需要单独进行处理,我们对实例化的类分离出namespace和类名

1
2
3
4
$name=strstr($className,'\\',true);//获取文件夹名字
然后处理特殊的路径,比如我们需要加载系统自带的db类,或者缓存类
然后判断文件是否存在,注意:在linux中系统自带的斜杠是不一样的
require_once $fileName;

总结

其实好多人关于命名空间和自动加载的认识是错误的,因为他们之间没有关系,之所以用命名空间自动加载不好用是因为你没有引入正确的文件,如此而已