怎樣理解ThinkPHP的Loader自動(dòng)加載

本篇文章給大家?guī)?lái)了thinkphp中l(wèi)oader自動(dòng)加載的相關(guān)知識(shí),主要包含了composer加載的相關(guān)知識(shí),希望對(duì)大家有幫助!

怎樣理解ThinkPHP的Loader自動(dòng)加載一、自動(dòng)加載loader源碼分析

1-1 學(xué)習(xí)目標(biāo)

  • 類(lèi)的自動(dòng)加載

  • 類(lèi)自動(dòng)加載的倆種方式

    立即學(xué)習(xí)PHP免費(fèi)學(xué)習(xí)筆記(深入)”;

  • spl_autoload_register必須會(huì)使用

  • 實(shí)現(xiàn)自定義文件的類(lèi)的自動(dòng)加載

1-2 Composer加載

怎樣理解ThinkPHP的Loader自動(dòng)加載

在這里插入圖片描述

在base.php中首先加載了loader類(lèi),接著調(diào)用了register這個(gè)方法。

怎樣理解ThinkPHP的Loader自動(dòng)加載

來(lái)到thinkphplibrary hinkLoader.php有一個(gè)register的方法,在這個(gè)方法里邊,我們先學(xué)習(xí)第一個(gè)知識(shí)點(diǎn)spl_autoload_register()聊聊spl_autoload_register前世今生和簡(jiǎn)單使用,直接點(diǎn)擊即可查看。

緊接著就是項(xiàng)目的根路徑和composer的路徑。

怎樣理解ThinkPHP的Loader自動(dòng)加載

在這里插入圖片描述

從這里開(kāi)始就是在加載composer文件,過(guò)程也是很簡(jiǎn)單

  • 判斷composer是否為目錄

  • 判斷路徑下面的autoload_static.php是否為文件

  • 引入autoload_static.php文件

  • 返回所有已經(jīng)聲明的所有類(lèi) ?數(shù)組返回

  • 獲取最后一個(gè)類(lèi)ComposerStaticInit30742487e00917c888d89ba216f165b9

  • 判斷ComposerStaticInit30742487e00917c888d89ba216f165b9中是否存在數(shù)組中的數(shù)據(jù)

怎樣理解ThinkPHP的Loader自動(dòng)加載

接著可以去vendorcomposerutoload_static.php文件中可以看到這倆個(gè)屬性

怎樣理解ThinkPHP的Loader自動(dòng)加載

這里有一段代碼估計(jì)有一部分同學(xué)會(huì)在這里繞一下self::${$attr} = $composerClass::${$attr};,這里的$attr就是’prefixLengthsPsr4′, ‘prefixDirsPsr4’, ‘fallbackDirsPsr4’, ‘prefixesPsr0’, ‘fallbackDirsPsr0’, ‘classMap’, ‘files’這些數(shù)據(jù),外層在加一個(gè)$符號(hào)。

從而在ComposerStaticInit30742487e00917c888d89ba216f165b9這個(gè)類(lèi)中直接獲取對(duì)應(yīng)的屬性值,也就是上圖的倆個(gè)屬性值。

怎樣理解ThinkPHP的Loader自動(dòng)加載

1-3 注冊(cè)命名空間

文件還是thinkphplibrary hinkLoader.php的register方法

在這里注冊(cè)了倆個(gè)命令空間,分別為think和traits。然后會(huì)進(jìn)入到addNamespace這個(gè)方法中

怎樣理解ThinkPHP的Loader自動(dòng)加載在addNamespace方法中,添加了Psr4空間

怎樣理解ThinkPHP的Loader自動(dòng)加載

接著來(lái)到addPsr4這個(gè)方法,會(huì)把這倆個(gè)命名空間都注冊(cè)到

ComposerStaticInit1e269472f484e157e90227b420ffca7a類(lèi)的$prefixLengthsPsr4和$prefixDirsPsr4這倆個(gè)屬性中

怎樣理解ThinkPHP的Loader自動(dòng)加載

為了驗(yàn)證上面做一個(gè)斷點(diǎn)調(diào)試,看到這些數(shù)據(jù)就應(yīng)該清晰了,至于traits也是一樣的注冊(cè)方式。

截止到這里命名空間就注冊(cè)完成了,接下來(lái)研究一下psr4命名空間是個(gè)什么東東。

怎樣理解ThinkPHP的Loader自動(dòng)加載

1-4 Psr4是什么玩意

psr是簡(jiǎn)單的理解就是文件路徑、自動(dòng)加載對(duì)應(yīng)類(lèi)的相關(guān)規(guī)范、目前TP5.1使用的是psr4規(guī)范

此處的類(lèi)是指class、接口、超類(lèi)結(jié)構(gòu)

一個(gè)完整的類(lèi)需要一下結(jié)構(gòu)()*

以下規(guī)范來(lái)源于PHP文檔

  • 完整的類(lèi)名必須要有一個(gè)頂級(jí)命名空間,被稱(chēng)為 “vendor namespace”;

  • 完整的類(lèi)名可以有一個(gè)或多個(gè)子命名空間;

  • 完整的類(lèi)名必須有一個(gè)最終的類(lèi)名;

  • 完整的類(lèi)名中任意一部分中的下滑線都是沒(méi)有特殊含義的;

  • 完整的類(lèi)名可以由任意大小寫(xiě)字母組成;

  • 所有類(lèi)名都必須是大小寫(xiě)敏感的。

以下是官方給的一個(gè)例子,這個(gè)psr規(guī)范能理解就盡量去理解它

怎樣理解ThinkPHP的Loader自動(dòng)加載

1-5 加載類(lèi)庫(kù)映射文件

到這里,肯定會(huì)有一個(gè)疑問(wèn),這里怎么沒(méi)有classmap.php這個(gè)文件。

怎樣理解ThinkPHP的Loader自動(dòng)加載

不急不慌,先執(zhí)行php think optimize:autoload把文件弄出來(lái)

怎樣理解ThinkPHP的Loader自動(dòng)加載

最終會(huì)走到addClassMap這個(gè)方法,在這個(gè)方法中,只是把classmap.php這個(gè)文件的數(shù)據(jù)賦值給$classMap 而已,沒(méi)有什么其它的用法

怎樣理解ThinkPHP的Loader自動(dòng)加載

1-6 自動(dòng)加載extend目錄

extend這個(gè)目錄用過(guò)TP框架的都多少用過(guò)的,在這個(gè)目錄里邊可以存放一下自定義的類(lèi)庫(kù)文件。

根據(jù)下圖可以看到就是使用addAutoLoadDir這個(gè)方法進(jìn)行加載的

怎樣理解ThinkPHP的Loader自動(dòng)加載

在方法中也僅僅是把extend的路徑賦值給了$fallbackDirsPsr4這個(gè)屬性。

怎樣理解ThinkPHP的Loader自動(dòng)加載

截止到這里L(fēng)oader::register();這部分就結(jié)束了,接著我們深入的看一下內(nèi)部實(shí)現(xiàn)和實(shí)踐案例。

在以上閱讀源碼中有四個(gè)屬性,簡(jiǎn)單的整理一下

怎樣理解ThinkPHP的Loader自動(dòng)加載

二、簡(jiǎn)說(shuō)類(lèi)的加載過(guò)程

怎樣理解ThinkPHP的Loader自動(dòng)加載

在這里插入圖片描述

在剛剛開(kāi)始解析這里的源碼時(shí)就有一個(gè)函數(shù)spl_autoload_register

當(dāng)需要使用的類(lèi)沒(méi)有被引入時(shí),這個(gè)函數(shù)會(huì)在PHP報(bào)錯(cuò)前被觸發(fā),未定義的類(lèi)名會(huì)被當(dāng)作參數(shù)傳入這里會(huì)直接去執(zhí)行thinkLoader::autoload這個(gè)方法

怎樣理解ThinkPHP的Loader自動(dòng)加載

經(jīng)過(guò)斷點(diǎn)第一個(gè)未加載的類(lèi)就是thinkError

怎樣理解ThinkPHP的Loader自動(dòng)加載

為什么是thinkError呢!可以在回到thinkphp/base.php看一下,當(dāng)自動(dòng)加載完執(zhí)行完成后第一個(gè)執(zhí)行的類(lèi)就是Error

怎樣理解ThinkPHP的Loader自動(dòng)加載

可以簡(jiǎn)單的做個(gè)測(cè)試,將這Error改為Kaka,進(jìn)行打印一下,這時(shí)的類(lèi)就改變?yōu)镵aka。到這里大家對(duì)這個(gè)類(lèi)的自動(dòng)加載機(jī)制就有一定的了解了。

當(dāng)使用的類(lèi)沒(méi)有被引入時(shí)會(huì)把這個(gè)類(lèi)當(dāng)做參數(shù)傳到thinkphp/library/think/Loader.php的autoload方法中。

怎樣理解ThinkPHP的Loader自動(dòng)加載

到這里在進(jìn)行看一下autoload這個(gè)方法

怎樣理解ThinkPHP的Loader自動(dòng)加載

先從findFile這個(gè)方法走,把未因?yàn)榈念?lèi)傳入這個(gè)方法中,在findFile這個(gè)方法中會(huì)直接從classMap這個(gè)屬性中直接把thinkError這個(gè)類(lèi)映射的文件直接返回出來(lái)

怎樣理解ThinkPHP的Loader自動(dòng)加載

將thinkError這個(gè)類(lèi)的完整路徑返回給autoload的file變量后,把win環(huán)境的大小寫(xiě)給判斷了一次。

然后直接使用include引入文件即可,直到返回。

直到這里就是一次完整的類(lèi)的自動(dòng)加載解析。

怎樣理解ThinkPHP的Loader自動(dòng)加載

雖然到這里結(jié)束了,但是還是得在提一點(diǎn)就是$classMap這個(gè)屬性,這個(gè)屬性是基于文件classmap.php來(lái)到,這個(gè)文件的生成也是需要執(zhí)行命令php think optimize:autoload生成的。

當(dāng)沒(méi)有生成這個(gè)文件時(shí)程序是如何執(zhí)行的呢!

之前的所有流程都是一樣的,只有在findFile這里不一樣,接下來(lái)進(jìn)行簡(jiǎn)單的梳理一下。

這時(shí)代碼肯定不會(huì)走classMap

怎樣理解ThinkPHP的Loader自動(dòng)加載

先獲取thinkError文件

怎樣理解ThinkPHP的Loader自動(dòng)加載

然后經(jīng)過(guò)Composer自動(dòng)加載中的倆個(gè)屬性進(jìn)行獲取命名空間,在把thinkError.php文件進(jìn)行拼接

怎樣理解ThinkPHP的Loader自動(dòng)加載

最終返回的結(jié)果也是D:phpstudy_proWWWThinkPHPSourceCodeAnalysis hinkphplibrary hinkError.php這個(gè)文件。

這里的代碼需要好好的閱讀一下。

類(lèi)的自動(dòng)加載到這里就是完全結(jié)束了。

三、自定義文件如何實(shí)現(xiàn)類(lèi)的自動(dòng)加載

先創(chuàng)建一個(gè)文件夾kaka

怎樣理解ThinkPHP的Loader自動(dòng)加載

這時(shí)在控制器index中引入文件Kaka.php

怎樣理解ThinkPHP的Loader自動(dòng)加載

直接進(jìn)行訪問(wèn),這時(shí)這個(gè)類(lèi)肯定會(huì)報(bào)錯(cuò),那么我們應(yīng)該怎么操作一下,就可以直接訪問(wèn)呢!

怎樣理解ThinkPHP的Loader自動(dòng)加載

在這里插入圖片描述

這個(gè)時(shí)候就提現(xiàn)到源碼的重要性了,還記得在自動(dòng)加載的register函數(shù)中,加載過(guò)extend目錄

怎樣理解ThinkPHP的Loader自動(dòng)加載

在這里插入圖片描述

這時(shí)在加一個(gè)kaka這個(gè)目錄,直接進(jìn)行訪問(wèn)一下

怎樣理解ThinkPHP的Loader自動(dòng)加載

沒(méi)毛病,直接就出來(lái)了。一切OK在這里在聊一下關(guān)于extent的加載方式

怎樣理解ThinkPHP的Loader自動(dòng)加載

在之前聊注冊(cè)自動(dòng)加載類(lèi)庫(kù)目錄只是說(shuō)明了一下只是把路徑存到了$fallbackDirsPsr4屬性,沒(méi)有細(xì)細(xì)說(shuō),接下來(lái)就是說(shuō)明這些了。

閱讀源碼只能是實(shí)現(xiàn)那然后查看那

怎樣理解ThinkPHP的Loader自動(dòng)加載

在這里插入圖片描述

只要是定義的類(lèi)都會(huì)進(jìn)去到autoload進(jìn)行自動(dòng)加載

同樣也會(huì)進(jìn)入到findFile這個(gè)方法

怎樣理解ThinkPHP的Loader自動(dòng)加載

在findFile這個(gè)方法中可以看到這段代碼,這個(gè)屬性是不是很熟悉,就是自動(dòng)加載extend目錄時(shí)添加到$fallbackDirsPsr4屬性的。

怎樣理解ThinkPHP的Loader自動(dòng)加載

當(dāng)在findFile中打印參數(shù)class時(shí)看一下數(shù)據(jù)

很清楚地可以看到testKaka這個(gè)類(lèi)

怎樣理解ThinkPHP的Loader自動(dòng)加載

怎樣理解ThinkPHP的Loader自動(dòng)加載

此時(shí)在打印一下這個(gè)$fallbackDirsPsr4屬性里邊返回的file

怎樣理解ThinkPHP的Loader自動(dòng)加載

然后就是使用__include_file來(lái)直接includeD:phpstudy_proWWWThinkPHPSourceCodeAnalysiskaka estKaka.php我們定義的文件。

以上的這個(gè)自定義文件如何實(shí)現(xiàn)類(lèi)的自動(dòng)加載,并且也就是extend的加載方式

(推薦學(xué)習(xí):thinkphp5

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊15 分享
站長(zhǎng)的頭像-小浪學(xué)習(xí)網(wǎng)月度會(huì)員