本系列的第二篇文章,這次我們聊聊:spl_autoload_register()函數(shù)
PHP的SPL庫作為擴展庫,已經(jīng)于5.3.0版本后默認保持開啟,成為PHP的一組強大的核心擴展庫。大家有時間可以多研究研究SPL里面的方法功能。而且,SPL中包含很多類庫喲,在設(shè)計模式的系列文章中,我們也會再次見到他們的身影!
這回我們建立一個文件,叫做spl_autoload_register.php,然后將下面的代碼復(fù)制進去吧:
<?php
spl_autoload_register(function( $className ){
require $className . '.php';
});
$m = new TestClass();
$m->show();
是不是和__autoload()很像,當然作用也很像。我們直接運行這個文件試試,會發(fā)現(xiàn)TestClass.php也正常的加載了進來。那么為啥不直接用__autoload()函數(shù),而使用sql_autoload_register()這么詭異的函數(shù),而且還有個神奇的閉包參數(shù)?。?!
我們先看看它的定義和格式
PHP官方文檔中的定義
注冊給定的函數(shù)作為 __autoload 的實現(xiàn)
沒錯,那個匿名函數(shù)就是一個__autoload()函數(shù),我們可以理解為給當前這個PHP文件中注冊一個__autoload()函數(shù),而使用匿名函數(shù)的原因呢?當然就是為了閉包特性,最主要的就是能夠帶來延遲加載(懶加載 )的實現(xiàn)!
另外,spl_autoload_register()函數(shù)不止是僅僅去注冊一個__autoload(),它實現(xiàn)并維護了一個__autoload()隊列。原來在一個文件中只能有一個__autoload()方法,但現(xiàn)在,你擁有的是一個隊列。
函數(shù)格式
spl_autoload_register ([ callable
throw = true [, bool $prepend = false ]]] ) : bool
有點長,我們一步步看:
- callable $autoload_function:閉包函數(shù),不多解釋了,上面已經(jīng)說了,不了解閉包函數(shù)的作用可以百度百度
- bool
autoload_function無法成功注冊時,是否拋出異常
- bool $prepend:如果是true,將會添加一個__autoload()函數(shù)到隊列的頂部
- 這個函數(shù)有返回值,成功或失敗
改造代碼
嗯,到這里好像有點復(fù)雜了,我們需要改造改造代碼這樣才能讓大家看得更清晰,先準備另一個需要加載 的類文件,就叫CaseClass.php好了
<?php
class CaseClass
{
public function show()
{
echo "Good!\n";
}
}
然后修改spl_autoload_register.php文件
<?php
// 使用匿名函數(shù)方式
spl_autoload_register(function( $className ){
echo "first==>\n";
require_once 'TestClass.php';
});
// 需要注冊的外部__autoload()實現(xiàn)
spl_autoload_register('CaseAutoLoad');
function CaseAutoLoad( $className ){
echo "second==>\n";
require_once 'CaseClass.php';
}
$m = new TestClass();
$m->show();
echo "--------\n";
$s = new CaseClass();
$s->show();
什么都別說了,直接運行吧,如果有報錯請檢查下哪里寫錯了,反正我這里沒錯~~
正常情況下應(yīng)該輸出這樣的內(nèi)容

- "first==>"是我們原來的spl_autoload_register()函數(shù)輸出的內(nèi)容,這里我們沒有使用$className來動態(tài)加載,而是只加載TestClass.php這一個文件
- 接下來我們便輸出了TestClass里面的show()方法的內(nèi)容。需要注意的是:這里可還沒有加載CaseClass.php這個文件哦,也就是現(xiàn)在我們已經(jīng)實現(xiàn)了懶加載了哦
- 接下來,我們想要實例化CaseClass對象,于是spl_autoload_register()維護的隊列發(fā)揮作用了。先走第一條,利用require_once()對于之前已經(jīng)加載過的TestClass.php不會再次加載了。但是這一個文件中并沒有找到我們需要的CaseClass對象,于是我們進入了隊列第二條,來到了CaseAutoLoad()方法中,CaseClass.php終于在這個方法中被require_once()進來了
到這里,你已經(jīng)知道了這個函數(shù)最大的作用就是維護的這個隊列并且可以延遲加載我們需要的文件。是不是感覺有點要走上人生巔峰了?不不不,你心里或許還在疑惑,這玩意跟Composer有啥關(guān)系?
請在您需要測試的目錄初始化一個Composer
- 進入vendor/composer/autoload_real.php中
- 在getLoader()方法中馬上就能發(fā)現(xiàn)spl_autoload_register()方法
- 然后在最底下有個
loader就是ClassLoader類
- 進入ClassLoader.php文件中,找到register()方法- 沒錯,里面還是一個spl_autoload_register()方法,這樣來看,這貨就是Composer的靈魂?。?!
OK,走到這里,其實在面試的時候就可以跟面試官司吹牛了,Composer的原理?spl_autoload_register()方法嘛。說不定確實有不少人就被你唬住了,但是,對于Composer來說,我們還有一個非常重要的方面不能忽略,可以將它看作是Composer的血肉,讓自動加載能夠有形,成為一個有靈魂有軀體的完整的人,這就是PSR規(guī)范中的PSR0和PSR4規(guī)范,下篇我們就聊聊這倆貨!
完整源碼:GitHub
===============
關(guān)注公眾號:【硬核項目經(jīng)理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、項目管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核項目經(jīng)理】
B站ID:482780532