文章大纲

通过代码示例说明php里__autoload与spl_autoload_register函数的区别

2022年12月20日 16:45

php框架里,有很多类文件。这些文件的引入,就需要借助自动加载函数来实现。

spl_autoload_register函数相当于__autoload的升级版,我们先来看看__autoload函数的用法。


1. __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目录,并在其中也新建了zhai.php文件。

文件目录结构如下所示:
-lib
lib/zhai.php
start.php
zhai.php

lib文件夹里zhai.php文件:
//lib文件夹里zhai.php文件
namespace Lib;

class Zhai
{
    public function sayHello()
    {
        echo 'hello in lib<br>';
    }
}

此时autoload函数不做任何修改,仍然能实现lib文件夹下文件的自动加载。
//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函数用来实现自动加载的缺点,就是需要调整引入文件的逻辑,来满足各种不同的情形。



2. __autoload在php8中移除

官方手册已提示:

本函数已自 PHP 7.2.0 起被废弃,并自 PHP 8.0.0 起被移除

本文为翟码农个人博客PHP分类下的原创文章,转载请注明出处:php里__autoload与spl_autoload_register函数的区别



3. 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函数所说的灵活性吧。




  • 2022年12月20日 14:22文章创建
  • 2022年12月20日 16:45文章发布
我要评论
评论列表
暂无评论,期待你的评论哦!
回到顶部