ThinkPHP5.1.x 框架源码分析之框架的灵魂

前端之家收集整理的这篇文章主要介绍了ThinkPHP5.1.x 框架源码分析之框架的灵魂前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、类的自动加载初始

框架的灵魂,类的自动加载

为什么说是框架灵魂呢,一般框架都会有类的自动加载,当引入文件很多的时候,就会需要用到。这一个也是很多人想去阅读源码时卡住的点

源码阅读

    @H_502_9@打开到入口文件 ../public/index.PHP 会看到这一段代码,此代码加载了 base.PHP 的核心文件
// 加载基础文件 [ ../public/index.PHP]
require __DIR__ . '/../thinkPHP/base.PHP';
    @H_502_9@在 base.PHP 中载入了一个 ThinkPHP 团队自己封装的底层基础类库。这个类库就是需要我们深入了解的 Loader 类。在载入后立即调用Loaderregister,并且下一句做好了 Error 错误处理
// 载入Loader类 [ ../thinkPHP/base.PHP]
require __DIR__ . '/library/think/Loader.PHP';
// 注册自动加载
Loader::register();
// 注册错误和异常处理机制
Error::register();
    @H_502_9@在 Loader.PHP 中的 也就是 register 方法中使用了 spl_autoload_register,这种自动注册的加载方式是很多框架都会有的,比如 Yii 这些。每一个框架实现的第一步都是类的自动加载
// 注册系统自动加载
spl_autoload_register($autoload ?: 'think\\Loader::autoload',true,true);

点击此处加入我的 企鹅群

二、自动加载 spl_autoload_register 初识

spl_autoload_register 的简介

    @H_502_9@

    spl_autoload_register 函数是实现自动加载未定义类功能的的重要方法

    @H_502_9@

    所谓的自动加载意思就是我们的 new 一个类的时候必须先 include 或者 require 的类文件,如果没有 include 或者 require,则会报错。

    @H_502_9@

    但是这样就必须在文件头部写上许多 include 或者 require 文件,非常麻烦。

    @H_502_9@

    为了使得没有 include 或者 require 类的时候也正常 new 一个类,所以有了自动加载的概念

    @H_502_9@

    也就是说 new 一个类之前不用事先包含类文件也可以正常 new ,这样我们的文件头部就不用包含许多 include(require)。这就是为什么说 spl_autoload_register 是框架灵魂。

spl_autoload_register 的三个参数

autoload_function 参数

这是一个函数 方法 名称,可以是 字符串 或者 数组 调用方法使用。这个函数 方法功能就是,来把需要 new 的类文件包含 include(require) 进来,这样 的时 new 候就不会找不到文件。其实就是封装整个项目的 includerequire 功能

可以理解为当我们 new 一个类,并且这个类文件没有被包含时候就会执行这个 autoload_function 方法

throw 参数

此参数设置了 autoload_function 无法成功注册时, spl_autoload_register() 是否抛出异常。

prepend 参数

如果是 truespl_autoload_register()添加函数到队列之首,而不是队列尾部。

栗子.1

如下:先举个错误的栗子,可以看到当我们直接 new 一个未包含 class类 文件时候会报错

在这里插入图片描述

栗子.2

如下:当使用 spl_autoload_register() 后当 new 一个未包含的类时候,会去执行 spl_autoload_register() 第一个参数函数名的函数,这个函数有一个参数就是需要 new 的类名,这个函数功能就是把这个类给包含进来(类名和文件名一致),这样就实现了自动加载功能

在这里插入图片描述

栗子.3

如下:当然我们也可以改成这样

在这里插入图片描述

Composer 自动加载

源码分析 (Loader.PHP

    @H_502_9@

    获取到定义好的所有类 get_declared_classes()

    @H_502_9@

    拿到 Composer 安装的类信息

    @H_502_9@

    ../vendor/composer/autoload_static.PHP 内信息放入变量内

    @H_502_9@

    打完收工,这里有疑问没关系,先接着看

 /** 存在 ../vendor/composer/ Composer目录则加载 */
 if (is_dir(self::$composerPath)) {
     if (is_file(self::$composerPath . 'autoload_static.PHP')) {
         /** 加载 ../vendor/composer/autoload_static.PHP  */
         require self::$composerPath . 'autoload_static.PHP';
         /** 返回所有已经定义的类  */
         $declaredClass = get_declared_classes();
         /** 获取到最后一个类  */
         $composerClass = array_pop($declaredClass);
         /** 查看 Composer 已经安装的包  */
         foreach (['prefixLengthsPsr4','prefixDirsPsr4','fallbackDirsPsr4','prefixesPsr0','fallbackDirsPsr0','classMap','files'] as $attr) {
             /** 将一些设定好的数据放入到变量内  */
             if (property_exists($composerClass,$attr)) {
                 self::${$attr} = $composerClass::${$attr};
             }
         }
     } else {
         self::registerComposerLoader(self::$composerPath);
     }
 }

源码分析 (autoload_static.PHP

    @H_502_9@

    大家可以看到,在上面定义好的数组里面就存在这两个内容 prefixLengthsPsr4,prefixDirsPsr4,files

    @H_502_9@

    Composer 的加载是在 autoload_static.PHP 取到的映射关系

    @H_502_9@

    以下是未安装任何包的源码

 public static $prefixLengthsPsr4 = array (
     't' => 
     array (
         'think\\composer\\' => 15,),'a' => 
     array (
         'app\\' => 4,);

 public static $prefixDirsPsr4 = array (
     'think\\composer\\' => 
     array (
         0 => __DIR__ . '/..' . '/topthink/think-installer/src','app\\' => 
     array (
         0 => __DIR__ . '/../..' . '/application',);
    @H_502_9@这个时候我使用 Composer 安装上 topthinkthink-helper,内部的映射关系就会变成以下这样
安装命令
$ composer require topthink/think-helper

在这里插入图片描述

    @H_502_9@

    首先是多了一个 files 值,这个是安装包的路径

    @H_502_9@

    prefixLengthsPsr4t 多了一个 think\\=>6。这个的意思也挺简单 think-helper 的命名空间是 think加上 \\ 就是 6 个字符 (\\ 中夹带转义)

    @H_502_9@

    prefixDirsPsr4 也一样相对与上一个做出一个路径映射

    @H_502_9@

    好了,源码就这样很简单。讲的不算清楚还望见谅!!!

举个栗子

    @H_502_9@一般在多人项目当中,我们一般会将 vendor 内的文件设置忽略。但是因为种种原因有很多人会出现有包文件但没有修改 autoload_static.PHP。或者举例一个场景:比如 A 需要用到一个插件,使用 Composer 下载好了之后。这个时候同事 B 偷懒直接将其插件文件复制过来。但是不管什么操作就是报错。那如何将一个复制的包载入到自动加载内呢

1、比如这个时候我存在一个 think-test 插件,命名空间是 think\test

在这里插入图片描述

2、修改 autoload_static.PHP

在这里插入图片描述

3、这样即可直接使用

在这里插入图片描述

点关注,不迷路

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。之前说过,PHP方面的技术点很多,也是因为太多了,实在是写不过来,写过来了大家也不会看的太多,所以我这里把它整理成了PDF和文档,如果有需要的可以

点击进入暗号: PHP+「平台」

在这里插入图片描述

在这里插入图片描述


更多学习内容可以访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、MysqL优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的 PHP技术交流群

猜你在找的PHP相关文章