php框架里,有很多类文件。这些文件的引入,就需要借助自动加载函数来实现。
spl_autoload_register函数相当于__autoload的升级版,我们先来看看__autoload函数的用法。
我写了两个文件start.php、zhai.php
//start.php function __autoload($class){ require_once(strtolower($class).".php"); } $obj = new Zhai(); $obj->sayHello();
由于Zhai这个类没有声明过,当程序执行到new时,就会自动先触发__autoload函数,来引入相关文件:
//zhai.php class Zhai { public function sayHello(){ echo "hello<br>"; } }
-lib lib/zhai.php start.php zhai.php
//lib文件夹里zhai.php文件 namespace Lib; class Zhai { public function sayHello() { echo 'hello in lib<br>'; } }
//start.php use Lib\Zhai as Zhai2; function __autoload($class){ require_once(strtolower($class).".php"); } $obj = new Zhai(); $obj->sayHello(); $obj = new Zhai2(); $obj->sayHello();
hello
hello in lib
但如果,文件命名跟类名不一样呢?例如,文件结构如下所示(添加了一个cache文件夹):
-cache cache/cache.zhai.php (文件名多了cache前缀) -lib lib/zhai.php start.php zhai.php
cache目录下zhai.php文件代码如下:
//cache目录下cache.zhai.php namespace Cache; class Zhai { public function sayHello() { echo 'hello in cache<br>'; } }
现在要想调用cache下Zhai类的sayHello方法,start.php里的__autoload函数里引入文件的逻辑就需要稍作调整,如下:
//start.php use Lib\Zhai as Zhai2; use Cache\Zhai as Zhai3; function __autoload($class){ if(strtolower(substr($class, 0, 5)) == 'cache'){ $new_class = str_replace("Cache\\", "Cache\\cache.", $class); require_once(strtolower($new_class).".php"); }else{ require_once(strtolower($class).".php"); } } $obj = new Zhai(); $obj->sayHello(); $obj = new Zhai2(); $obj->sayHello(); $obj = new Zhai3(); $obj->sayHello();
结果正常输出:
hello
hello in lib
hello in cache
如此可见,__autoload函数用来实现自动加载的缺点,就是需要调整引入文件的逻辑,来满足各种不同的情形。
官方手册已提示:
本函数已自 PHP 7.2.0 起被废弃,并自 PHP 8.0.0 起被移除
本文为翟码农个人博客PHP分类下的原创文章,转载请注明出处:php里__autoload与spl_autoload_register函数的区别
知道了__autoload函数的缺点,那就知道它的升级版函数spl_autoload_register应该就解决了这一缺点。
基于同样的目录,start.php文件的代码改写如下:
//start.php use Lib\Zhai as Zhai2; use Cache\Zhai as Zhai3; function loadCommon($class){ $file_name = strtolower($class).".php"; //此处一定要进行is_file判断,当require_once引入的文件不存在时,则会报错,程序就会中断执行 if(is_file($file_name)){ require_once(strtolower($class).".php"); } } function loadCacheFile($class){ if(strtolower(substr($class, 0, 5)) == 'cache'){ $new_class = str_replace("Cache\\", "Cache\\cache.", $class); require_once(strtolower($new_class).".php"); } } spl_autoload_register('loadCommon'); spl_autoload_register('loadCacheFile'); $obj = new Zhai(); $obj->sayHello(); $obj = new Zhai2(); $obj->sayHello(); $obj = new Zhai3(); $obj->sayHello();
可以看出,loadCommon函数,负责引入和start.php文件在同一级目录下的文件,以及lib文件夹下文件命名跟类名一致(除了大小写)的情形。
而loadCacheFile函数,则负责引入cache目录下的文件。
网上把这两个函数其中实现加载文件的逻辑,称为加载机制。
上面代码,我们就可以描述为:有两种不同的加载机制。
如果再来一种加载机制,我们直接再添加一个函数即可,就不用像__autoload那样,在其内部补充逻辑,这大概也就是spl_autoload_register函数所说的灵活性吧。