thinkphp5.1框架解析(二):自动加载

继 生命周期的第二篇,大家尽可放心,不会随便鸽文章的

第一篇中,我们提到了入口脚本,也说了,里面注册了自动加载的功能

自动加载机制

php 的自动加载是Loader 类中实现的,这个类在 base.php 中被引入

//base .php
// 载入Loader类
require __DIR__ . '/library/think/Loader.php';

// 注册自动加载
Loader::register();

我们程序在这里执行了 Loader 中静态方法 ,同时这也是一个全部的类register() 我们进入 Loader.php ,按照上面执行顺序看看其核心是什么?
此方法行数过长,我们一点一点来分析

// 注册系统自动加载
        spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);

这就是注册我们的自动加载函数,$autoload 这个变量是传的参数,然而我查找 tp5.1 源码,也没有发现有任何传参的动作。我认为是多余的参数,直接写'think\\Loader::autoload' 就可以了。

如果不了解这个函数的同学,请看文章最顶部的那个连接,上面有详细讲解。

$rootPath = self::getRootPath();
        self::$composerPath = $rootPath . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR;

        // Composer自动加载支持
        if (is_dir(self::$composerPath)) {
            if (is_file(self::$composerPath . 'autoload_static.php')) {
                require self::$composerPath . 'autoload_static.php';

                $declaredClass = get_declared_classes();
                $composerClass = array_pop($declaredClass);

                foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
                    if (property_exists($composerClass, $attr)) {
                        self::${$attr} = $composerClass::${$attr};
                    }
                }
            } else {
                self::registerComposerLoader(self::$composerPath);
            }
        }

为了支持 composer 拓展,在自动注册时候,把composer 也顺带一起注册了,把composer 目录映射关系存放到 prefixDirsPsr4这个静态变量中,方便对拓展的调用。

// 注册命名空间定义
        self::addNamespace([
            'think'  => __DIR__,
            'traits' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'traits',
        ]);

        // 加载类库映射文件
        if (is_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php')) {
            self::addClassMap(__include_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php'));
        }

        // 自动加载extend目录
        self::addAutoLoadDir($rootPath . 'extend');

这后面的代码都大同小异,都是把 所需要用到的类,映射到prefixDirsPsr4这个静态变量中。到时候方便我们使用命名空间进行调用。

register() 函数这里就大概分析结束了。 接下来我们讲一讲autoload()

自动加载

上面我们讲spl_autoload_register的时候,说他注册了 autoload()函数,使我们在找不到类的情况下,来调用此函数。

//函数整体内容
public static function autoload($class)
    {
        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;
            }

            __include_file($file);
            return true;
        }
    }

我们截取片段一点一点分析。

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

这一段是判断我们是否是使用了 TP5.1的 静态调用接口(Facade) ,具体解释可以参照官方文档的解释,这个是在 base.php的末尾注册的

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

            // Win环境严格区分大小写
            if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
                return false;
            }

            __include_file($file);
            return true;
        }

findFile($class) 主要功能是根据类的名称,配合我们之前存储映射关系的静态数组prefixDirsPsr4来找寻文件的目录。

如果找到就消除 linux 和 window 对路径名称的差异。(linux 严格区分大小写,而win 没有严格区分)

这里主要是担心在window环境下,路径名称大小写没分,所以我们根据linux的目录规则重写了文件路径

之后再加我们的目录文件

如果没有找到,就报错并写入日志

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值