PHP 实现自动加载(含有命名空间) spl_autoload_register

本文介绍了如何使用PHP的`spl_autoload_register`函数配合PSR-4规范,实现自动加载功能,简化类文件映射并提升代码组织效率。通过实例解析,展示了如何通过自动加载器根据类名动态查找和包含对应的文件。
摘要由CSDN通过智能技术生成

PHP 实现自动加载(含有命名空间) spl_autoload_register

ps:

  • 看了一些别的博主关于自动加载的机制实现 此处来记录一下
  • 原文链接 https://www.cnblogs.com/chihuobao/p/9895202.html…

文件结构树
在这里插入图片描述

//index.php
<?php
require './autoload.php';

new \vender\os\Linux();

?>
// Linux.php Window.php 类似
<?php

namespace vender\os;

class Linux 
{
    function __construct()
    {
        echo '<h1>' . __CLASS__ . '</h1>';
    }
}

?>
spl_autoload_register 函数的功能就是把传入的函数(参数可以为回调函数或函数名称形式)注册到 SPL __autoload 函数队列中,并移除系统默认的 __autoload() 函数。

一旦调用 spl_autoload_register() 函数,当调用未定义类时,系统就会按顺序调用注册到 spl_autoload_register() 函数的所有函数,而不是自动调用 __autoload() 函数。
//autoload.php
<?php
spl_autoload_register(function ($class) { 

    // 限定类名路径映射
    $class_map = array(
        // 限定类名 => 文件路径
        'vender\\os\\Linux' => './vender/os/Linux.php',
        'vender\\os\\Window' => './vender/os/Window.php',
    );

    // 根据类名确定文件名
    $file = $class_map[$class];


    // 引入相关文件
    if (file_exists($file)) {
        include $file;
    }
});
?>

这里我们使用了一个数组去保存类名与文件路径的关系,这样当类名传入时,自动加载器就知道该引入哪个文件去加载这个类了。

但是一旦文件多起来的话,映射数组会变得很长,这样的话维护起来会相当麻烦。如果命名能遵守统一的约定,就可以让自动加载器自动解析判断类文件所在的路径。接下来要引用的PSR-4规范 就是一种被广泛采用的约定方式。

PSR-4 规范中必须要有一个顶级命名空间,它的意义在于表示某一个特殊的目录(文件基目录)。子命名空间代表的是类文件相对于文件基目录的这一段路径(相对路径),类名则与文件名保持一致(注意大小写的区别)。

举个例子:在全限定类名 \app\view\news\Index 中,如果 app 代表 C:\Baidu,那么这个类的路径则是 C:\Baidu\view\news\Index.php

我们就以解析 \app\view\news\Index 为例,编写一个简单的 Demo:
$class = 'app\view\news\Index';

/* 顶级命名空间路径映射 */
$vendor_map = array(
    'app' => 'C:\Baidu',
);

/* 解析类名为文件路径 */
$vendor = substr($class, 0, strpos($class, '\\')); // 取出顶级命名空间[app]
$vendor_dir = $vendor_map[$vendor]; // 文件基目录[C:\Baidu]
$rel_path = dirname(substr($class, strlen($vendor))); // 相对路径[/view/news]
$file_name = basename($class) . '.php'; // 文件名[Index.php]

/* 输出文件所在路径 */
echo $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;

具体实现:

// autoload.php
<?php

 /*
         * 注册一个自动加载函数,就是本类钟的 autoload 方法
         * 第二个参数为true表示注册失败的时候会抛出异常
         * 第三个参数为true表示该自动加载函数是加入到队列的头部,自动加载函数是有很多的,可以认为是一个队列,默认false值是往队尾添加
         * 加载类的时候,会先从队头的自动加载函数去寻找类和实例化,这里是true,就是作为第一个去执行的自动加载函数。
         */
spl_autoload_register('Loader::autoload',true,true); // 注册自动加载

/**
 * 自动加载类
 * Class Loader
 */
class Loader{


    /**
     * @var array  路径映射
     */
    public static $vendorMap = array(
        'vender' => __DIR__ . DIRECTORY_SEPARATOR . 'vender',
    );


    /**
     * 自动加载器
     * @param $class
     */
    public static function autoload($class)
    {   
        
        $file = self::findFile($class);

        if (file_exists($file)) {
            self::includeFile($file);
        }
    }


    /**
     * 解析文件路径
     * @param $class
     * @return bool|string
     */
    private static function findFile($class)
    {   
        $vendor = substr($class, 0, strpos($class, '\\')); // 顶级命名空间

        if(array_key_exists($vendor, self::$vendorMap)){
            $vendorDir = self::$vendorMap[$vendor]; // 文件基目录
            $filePath = substr($class, strlen($vendor)) . '.php'; // 文件相对路径
            return strtr($vendorDir . $filePath, '\\', DIRECTORY_SEPARATOR); // 文件标准路径
        }
        return false;
        
    }


    /**
     * 引入文件
     * @param $file
     */
    private static function includeFile($file)
    {   
        if (is_file($file)) {
            include $file;
        }
    }

}

结果:
在这里插入图片描述
至此 ,就简单实现了psr4 自动加载
示例中的代码其实就是 ThinkPHP 自动加载器源码的精简版,它是 ThinkPHP 5 能实现惰性加载的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值