TP5源码分析-加载基础文件【Loader类入口register函数分析2】

1、主要分析跳转后最终达到什么效果
  • 上一节我大概把register分为了五步 这一节我们从简单的开始 从第三步开始
    我还是把源码附上
public static function register($autoload = '')
    {
        // 【1】注册系统自动加载
        // 【2】Composer自动加载支持
        // 【3】注册命名空间定义
        self::addNamespace([
            'think'  => __DIR__,
            'traits' => dirname(__DIR__) . DIRECTORY_SEPARATOR .         'traits', 
        ]);
        // 【4】加载类库映射文件
        // 【5】自动加载extend目录
       
    }
  • 第三步 注册特定的顶级命名空间 think 、 traits 对应绝对路径
  • 跳转至
  public static function addNamespace($namespace, $path = '')
    { 
       //把前缀think 和 path 通过addPsr4 添加到$prefixLengthsPsr4 $prefixDirsPsr4 
        if (is_array($namespace)) {
            foreach ($namespace as $prefix => $paths) {
                self::addPsr4($prefix . '\\', rtrim($paths, DIRECTORY_SEPARATOR), true);
            }
        } else {
            self::addPsr4($namespace . '\\', rtrim($path, DIRECTORY_SEPARATOR), true);
        }
    }
  • 分析一下跳转这个函数addPsr4的作用是什么
    请看里面的注释
private static function addPsr4($prefix, $paths, $prepend = false)
    {
        //$prefix --->think\
        //$paths  ---->D:\www\ThinkPHP_V5.1.39\thinkphp\library\think
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                self::$fallbackDirsPsr4 = array_merge(
                    (array) $paths,
                    self::$fallbackDirsPsr4
                );
            } else {
                self::$fallbackDirsPsr4 = array_merge(
                    self::$fallbackDirsPsr4,
                    (array) $paths
                );
            }
        } elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            // think\  $prefix[$length - 1] 刚好取出\
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }

            self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            self::$prefixDirsPsr4[$prefix]                = (array) $paths;
            var_dump(self::$prefixLengthsPsr4);
            var_dump(self::$prefixDirsPsr4);
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            self::$prefixDirsPsr4[$prefix] = array_merge(
                (array) $paths,
                self::$prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            self::$prefixDirsPsr4[$prefix] = array_merge(
                self::$prefixDirsPsr4[$prefix],
                (array) $paths
            );
        }
    }
  • 第一次只能走我们var_dump里面的分支 那么我把打印的结果给出来你就知道什么意思了

在这里插入图片描述
在这里插入图片描述
知道了这个打印结果我知道你还是很懵逼,不着急我们再看下面一个例子

2、举例说明问题
  • 首先我在D:\www\ThinkPHP_V5.1.39\thinkphp\library\traits\controller\Jump.php
    里面定一个方法test, 然后在控制器里面去调用,再来观察是怎么自动加载的

Jump.php 在这里插入图片描述
Index控制器
在这里插入图片描述

  • 加载过程 首先走register 第一步【1】
 // 【1】注册系统自动加载
        spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
  • 瞧瞧autoload
    // 自动加载
    public static function autoload($class)
    {

       // echo $class;
       // echo '<br>';
        //返回别名
        if (isset(self::$classAlias[$class])) {

            return class_alias(self::$classAlias[$class], $class);
        }

        if ($file = self::findFile($class)) {

            // Win环境严格区分大小写
            if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
                return false;
            }
          // var_dump($file);
            __include_file($file);
            return true;
        }
    }
  • 主要是看findFile
    private static function findFile($class)
    {
        if (!empty(self::$classMap[$class])) {
            // 类库映射
            return self::$classMap[$class];
        }

        // 查找 PSR-4
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';
        
        $first = $class[0];// traits/   t  取出第一个字母
        //重点就在在这里 通过前缀 长度 替换路径 
        if (isset(self::$prefixLengthsPsr4[$first])) {
            foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {
                if (0 === strpos($class, $prefix)) {
                    foreach (self::$prefixDirsPsr4[$prefix] as $dir) {
                        if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
                            var_dump($file);
                            return $file;
                        }
                    }
                }
            }
        }

        // 查找 PSR-4 fallback dirs
        foreach (self::$fallbackDirsPsr4 as $dir) {
            if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // 查找 PSR-0
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
            . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . '.php';
        }

        if (isset(self::$prefixesPsr0[$first])) {
            foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // 查找 PSR-0 fallback dirs
        foreach (self::$fallbackDirsPsr0 as $dir) {
            if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        return self::$classMap[$class] = false;
    }

我把var_dump打印结果摆出来你就知道了

在这里插入图片描述

知道了吧
我们看看autoload 里面调用了一个函数 __include_file($file);

function __include_file($file)
{

    return include $file;
}

到此你就知道怎么回事了

3、举一反三
  • 现在我想要加一个其他的命名空间是不是可以照葫芦画瓢了

在这里插入图片描述
在这里插入图片描述

到此就分析到这里 如果还是很懵逼 别着急 建议先看看psr-4 这里其他的文章可以先看看 我把链接贴出来 1、prs0
2、psr-0 和 psr-4的区别
3、深入解析 composer 的自动加载原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值