❝想了好久終於要開始系列文章的編寫了,指望是寫出提高和麪試均可以搞定的系列文章。當你看到本文時,若是你發現咔咔沒有編寫到的面試熱點問題或者技術難點,期待評論區指出,一塊兒完善。php
❞
前言
目前在整理PHP進階路線圖,若有好的建議咔咔會第一時間進行收錄。web
1、自動加載loader源碼分析
1-1 學習目標
-
類的自動加載 -
類自動加載的倆種方式 -
spl_autoload_register必須會使用 -
實現自定義文件的類的自動加載
1-2 Composer加載
從上圖咔咔給的解析圖,在base.php中首先加載了loader類,接着調用了register這個方法。面試
來到thinkphp\library\think\Loader.php
有一個register的方法,在這個方法裏邊,咱們先學習第一個知識點spl_autoload_register()
聊聊spl_autoload_register前世此生和簡單使用,直接點擊便可查看。thinkphp
緊接着就是項目的根路徑和composer的路徑。數組
從這裏開始就是在加載composer文件,過程也是很簡單微信
-
1.判斷composer是否爲目錄 -
2.判斷路徑下面的autoload_static.php是否爲文件 -
3.引入autoload_static.php文件 -
4.返回全部已經聲明的全部類 數組返回 -
5.獲取最後一個類ComposerStaticInit30742487e00917c888d89ba216f165b9 -
6.判斷ComposerStaticInit30742487e00917c888d89ba216f165b9中是否存在數組中的數據
接着能夠去vendor\composer\autoload_static.php文件中能夠看到這倆個屬性composer
這裏有一段代碼估計有一部分同窗會在這裏繞一下self::${$attr} = $composerClass::${$attr};
,這裏的$attr
就是'prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'
這些數據,外層在加一個$
符號。框架
從而在ComposerStaticInit30742487e00917c888d89ba216f165b9
這個類中直接獲取對應的屬性值,也就是上圖的倆個屬性值。編輯器
1-3 註冊命名空間
文件仍是thinkphp\library\think\Loader.php
的register
方法函數
在這裏註冊了倆個命令空間,分別爲think和traits。而後會進入到addNamespace這個方法中在addNamespace
方法中,添加了Psr4空間
接着來到addPsr4這個方法,會把這倆個命名空間都註冊到ComposerStaticInit1e269472f484e157e90227b420ffca7a類的$prefixLengthsPsr4和$prefixDirsPsr4這倆個屬性中
爲了驗證上面作一個斷點調試,看到這些數據就應該清晰了,至於traits
也是同樣的註冊方式。
截止到這裏命名空間就註冊完成了,接下來研究一下psr4命名空間是個什麼東東。
1-4 Psr4是什麼玩意
psr是簡單的理解就是文件路徑、自動加載對應類的相關規範、目前TP5.1使用的是psr4規範
此處的類是指class、接口、超類結構
一個完整的類須要一下結構\<命名空間>(\<子命名空間>)*\<類名>
如下規範來源於PHP文檔
-
完整的類名必需要有一個頂級命名空間,被稱爲 "vendor namespace";
-
完整的類名能夠有一個或多個子命名空間;
-
完整的類名必須有一個最終的類名;
-
完整的類名中任意一部分中的下滑線都是沒有特殊含義的;
-
完整的類名能夠由任意大小寫字母組成;
-
全部類名都必須是大小寫敏感的。
如下是官方給的一個例子,這個psr規範能理解就儘可能去理解它
1-5 加載類庫映射文件
到這裏,確定會有一個疑問,這裏怎麼沒有classmap.php這個文件。不急不慌,先執行php think optimize:autoload
把文件弄出來最終會走到addClassMap
這個方法,在這個方法中,只是把classmap.php
這個文件的數據賦值給$classMap
而已,沒有什麼其它的用法
1-6 自動加載extend目錄
extend這個目錄用過TP框架的都多少用過的,在這個目錄裏邊能夠存放一下自定義的類庫文件。
根據下圖能夠看到就是使用addAutoLoadDir
這個方法進行加載的
在方法中也僅僅是把extend的路徑賦值給了$fallbackDirsPsr4
這個屬性。
截止到這裏Loader::register();
這部分就結束了,接着咱們深刻的看一下內部實現和實踐案例。
在以上閱讀源碼中有四個屬性,簡單的整理一下
2、簡說類的加載過程
在剛剛開始解析這裏的源碼時就有一個函數spl_autoload_register
當須要使用的類沒有被引入時,這個函數會在PHP報錯前被觸發,未定義的類名會被看成參數傳入這裏會直接去執行think\\Loader::autoload
這個方法
通過斷點第一個未加載的類就是think\Error
爲何是think\Error呢!能夠在回到thinkphp/base.php
看一下,當自動加載完執行完成後第一個執行的類就是Error
能夠簡單的作個測試,將這Error改成Kaka,進行打印一下,這時的類就改變爲Kaka。到這裏你們對這個類的自動加載機制就有必定的瞭解了。
當使用的類沒有被引入時會把這個類當作參數傳到thinkphp/library/think/Loader.php
的autoload
方法中。
到這裏在進行看一下autoload這個方法
先從findFile這個方法走,把未引入的類傳入這個方法中,在findFile這個方法中會直接從classMap這個屬性中直接把think\Error這個類映射的文件直接返回出來
將think\Error這個類的完整路徑返回給autoload
的file
變量後,把win環境的大小寫給判斷了一次。
而後直接使用include
引入文件便可,直到返回。
直到這裏就是一次完整的類的自動加載解析。
雖然到這裏結束了,可是仍是得在提一點就是$classMap
這個屬性,這個屬性是基於文件classmap.php
來到,這個文件的生成也是須要執行命令php think optimize:autoload
生成的。
當沒有生成這個文件時程序是如何執行的呢!
以前的全部流程都是同樣的,只有在findFile
這裏不同,接下來進行簡單的梳理一下。
這時代碼確定不會走classMap
先獲取think\Error文件
而後通過Composer自動加載中的倆個屬性進行獲取命名空間,在把think\Error.php文件進行拼接
最終返回的結果也是D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\thinkphp\library\think\Error.php
這個文件。
這裏的代碼須要好好的閱讀一下。
類的自動加載到這裏就是徹底結束了。
3、自定義文件如何實現類的自動加載
先建立一個文件夾kaka
這時在控制器index中引入文件Kaka.php
直接進行訪問,這時這個類確定會報錯,那麼咱們應該怎麼操做一下,就能夠直接訪問呢!
這個時候就體現到源碼的重要性了,還記得在自動加載的register
函數中,加載過extend目錄
這時在加一個kaka這個目錄,直接進行訪問一下
沒毛病,直接就出來了。一切OK在這裏在聊一下關於extent的加載方式
在以前聊註冊自動加載類庫目錄只是說明了一下只是把路徑存到了$fallbackDirsPsr4
屬性,沒有細細說,接下來就是說明這些了。
閱讀源碼只能是實現那而後查看那
只要是定義的類都會進去到autoload進行自動加載
一樣也會進入到findFile
這個方法
在findFile這個方法中能夠看到這段代碼,這個屬性是否是很熟悉,就是自動加載extend目錄時添加到$fallbackDirsPsr4
屬性的。
當在findFile中打印參數class時看一下數據
很清楚地能夠看到test\Kaka
這個類
此時在打印一下這個$fallbackDirsPsr4
屬性裏邊返回的file
而後就是使用__include_file
來直接includeD:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\kaka\test\Kaka.php
咱們定義的文件。
以上的這個自定義文件如何實現類的自動加載,而且也就是extend
的加載方式
4、總結
關於類自動加載的全部流程就完成了,若有錯誤之處能夠在評論區哦!
❝堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。但願在偌大互聯網中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。
❞
本文分享自微信公衆號 - PHP初學者必看(PHP0022)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。