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

一、类的自动加载初始

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

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

源码阅读

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

点击此处加入我的 企鹅群

二、自动加载 spl_autoload_register 初识

spl_autoload_register 的简介

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

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

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

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

  5. 也就是说 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)

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

  2. 拿到 Composer 安装的类信息

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

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

 /** 存在 ../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)

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

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

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

 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',
     ),
 );
  1. 这个时候我使用 Composer 安装上 topthinkthink-helper,内部的映射关系就会变成以下这样
安装命令
$ composer require topthink/think-helper
在这里插入图片描述
  1. 首先是多了一个 files 值,这个是安装包的路径

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

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

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

举个栗子

  • 一般在多人项目当中,我们一般会将 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技术交流群

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容