PHP SPL擴(kuò)展庫(kù)簡(jiǎn)單使用

1. __autoload

這是一個(gè)自動(dòng)加載函數(shù),在PHP5中,當(dāng)我們實(shí)例化一個(gè)未定義的類(lèi)時(shí),就會(huì)觸發(fā)此函數(shù)。看下面例子:

./myClass.php
<?php
class myClass {
    public function __construct() {
        echo "myClass init'ed successfuly!!!";
    }
}
?>
./index.php
<?php
// we've writen this code where we need
function __autoload($classname) {
    $filename = "./". $classname .".php";
    include_once($filename);
}
// we've called a class ***
$obj = new myClass();
?>

從上面能看到這是兩個(gè)文件,下面的index.php 中,new了個(gè) myClass類(lèi),但是明顯本文件不存在,現(xiàn)在就會(huì)自動(dòng)調(diào)用 __autoload函數(shù),并 把 “myClass”這個(gè)類(lèi)名字符串 直接作為參數(shù)傳給__autoload, 此時(shí)自動(dòng)加載函數(shù)內(nèi)部就可以引入該文件了,引入后就正常初始化該類(lèi)了。 該函數(shù)在PHP 7.2.0后被廢棄了。

2. spl_autoload_register

spl_autoload_register 可以將 函數(shù)自動(dòng)注冊(cè),也就是說(shuō),當(dāng)PHP文件內(nèi)訪問(wèn)了一個(gè)不存在的類(lèi)時(shí),會(huì)自動(dòng)去調(diào)用該函數(shù),然后執(zhí)行該函數(shù)內(nèi)部的函數(shù),看起來(lái)和 autoload的作用是一樣的。但是其實(shí)spl_autoload_register 這個(gè)函數(shù)功能更強(qiáng)大, autoload的參數(shù) 僅僅是一個(gè)函數(shù)名,這是定死的。并且只能聲明一次, 使用了autoload后,就不能再次使用該函數(shù)了。

請(qǐng)注意:一個(gè)項(xiàng)目中只能有一個(gè)__autoload, 如果在PHP在執(zhí)行過(guò)程中遇到兩個(gè)__autoload會(huì)直接報(bào)錯(cuò)的。

很明顯,autoload無(wú)法滿足要求, 所以就有了SPL擴(kuò)展,spl_autoload_register接受函數(shù)名或閉包,或數(shù)組作為參數(shù),在閉包內(nèi)部,即可引入對(duì)應(yīng)的文件了。并且spl_autoload_register可以注冊(cè)一個(gè) 自動(dòng)加載隊(duì)列,先注冊(cè)的,先調(diào)用。

參數(shù) 
autoload_function
欲注冊(cè)的自動(dòng)裝載函數(shù)。如果沒(méi)有提供任何參數(shù),則自動(dòng)注冊(cè) autoload 的默認(rèn)實(shí)現(xiàn)函數(shù)spl_autoload()。
throw
此參數(shù)設(shè)置了 autoload_function 無(wú)法成功注冊(cè)時(shí), spl_autoload_register()是否拋出異常。
prepend
如果是 true,spl_autoload_register() 會(huì)添加函數(shù)到隊(duì)列之首,而不是隊(duì)列尾部。

可以結(jié)合require_once一起使用。如:

function_1(){
    $clsName = str_replace("\\",DIRECTORY_SEPARATOR, $class_name);
    if (is_file(__DIR__.DIRECTORY_SEPARATOR."src".DIRECTORY_SEPARATOR.$clsName . '.php')) {
        //文件內(nèi)部有類(lèi)名 為 TestClass_1的類(lèi)
        require_once(__DIR__.DIRECTORY_SEPARATOR."src".DIRECTORY_SEPARATOR.$clsName.'.php'); 
    }
}
function_2(){
    $clsName = str_replace("\\",DIRECTORY_SEPARATOR, $class_name);
    if (is_file(__DIR__.DIRECTORY_SEPARATOR."Module".DIRECTORY_SEPARATOR.$clsName . '.php')) {
        //文件內(nèi)部有類(lèi)名為T(mén)estClass_2的類(lèi)
        require_once(__DIR__.DIRECTORY_SEPARATOR."Module".DIRECTORY_SEPARATOR.$clsName.'.php');
    }
}
spl_autoload_register('function_1');
spl_autoload_register('function_2');
$obj = new TestClass_2();  //當(dāng)前沒(méi)有TestClass_2這個(gè)類(lèi),于是自動(dòng)調(diào)用function_1, 引入了文件,但是引入的文件中仍然沒(méi)有TestClass_2這個(gè)類(lèi),于是又自動(dòng)調(diào)用function_2, 引入了文件,此時(shí)正常初始化

3.相關(guān)的其他SPL函數(shù)

file

3.1 spl_autoload_call

該函數(shù)是需要用戶顯示調(diào)用所有已注冊(cè)的 autoload函數(shù)的。 作用在 spl_autoload_register之后。 傳入函數(shù)名字即可。即可手動(dòng)引入文件了。

3.2 spl_autoload_functions

可以獲取到所有已經(jīng)注冊(cè)的autoload函數(shù), 也是作用在 spl_autoload_register之后的。

3.3 spl_autoload_extensions

注冊(cè)并返回spl_autoload函數(shù)使用的默認(rèn)文件擴(kuò)展名, 但是此接口和spl_autoload函數(shù),用處不大。spl_autoload 是autoload的默認(rèn)實(shí)現(xiàn),意思就是spl_autoload對(duì)autoload進(jìn)行了又一次封裝,在默認(rèn)情況下,本函數(shù)先將類(lèi)名轉(zhuǎn)換成小寫(xiě),再在小寫(xiě)的類(lèi)名后加上 .inc 或 .php 的擴(kuò)展名作為文件名,然后在所有的包含路徑(include paths)中檢查是否存在該文件。

__autoload 函數(shù)是用來(lái)處理自動(dòng)加載的函數(shù),在 PHP 找不到指定類(lèi)時(shí)就會(huì)去調(diào)用自動(dòng)加載類(lèi),加載所需要的類(lèi)。
__autoload 只是一個(gè)抽象定義,實(shí)現(xiàn)(實(shí)現(xiàn)就是定義如何加載,加載的規(guī)則是什么,加載的文件是什么等等)是交給用戶的,而 spl_autoload 則是 SPL 所定義的 autoload 一種實(shí)現(xiàn)。spl_autoload 函數(shù)所實(shí)現(xiàn)的加載規(guī)則就是去 include paths 中查找對(duì)于的類(lèi)。spl_autoload 遵循是是 psr-0 的載入規(guī)則,而 include paths 就是載入時(shí)被查詢的路徑。
其他自己實(shí)現(xiàn)的 autoload 類(lèi)都可以通過(guò) spl_autoload_register 進(jìn)行注冊(cè),注冊(cè)之后就可以在需要類(lèi)時(shí)自動(dòng)調(diào)用被注冊(cè)的方法進(jìn)行加載了。 spl_autoload 也是 autoload 的一種實(shí)現(xiàn),按理也是需要注冊(cè)的,只不過(guò)因?yàn)槭莾?nèi)部的默認(rèn)實(shí)現(xiàn),所有已經(jīng)自動(dòng)注冊(cè)在 PHP 里了。

spl_autoload 如今來(lái)看并沒(méi)有太多用處,應(yīng)該是因?yàn)闅v史問(wèn)題殘留在 PHP 中的,目前絕大多數(shù)程序都沒(méi)有使用 spl_autoload 去做自動(dòng)加載,因?yàn)樗囊?guī)則已經(jīng)定死,并不適合衍生一些功能。

因?yàn)?PHP 只有一個(gè)自動(dòng)加載方法,所以 SPL 的 spl_autoload 和 spl_autoload_register 要爭(zhēng)搶這個(gè)方法,所以在 SPL 的 C 實(shí)現(xiàn)中,用了好多折衷的辦法。在沒(méi)有使用 spl_autoload_register 注冊(cè)任何自定的自動(dòng)加載函數(shù)時(shí), PHP 的自動(dòng)加載方法是掛在 spl_autoload 下的,而 spl_autoload_register 注冊(cè)了自動(dòng)加載函數(shù)后,PHP 的自動(dòng)加載方法是掛在 spl_autoload_call 這個(gè)方法下的,而 spl_autoload 也會(huì)成為一個(gè)備選項(xiàng)進(jìn)入 spl_autoload_register 的自動(dòng)加載隊(duì)列。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在使用PHP的OO模式開(kāi)發(fā)系統(tǒng)時(shí),通常大家習(xí)慣上將每個(gè)類(lèi)的實(shí)現(xiàn)都存放在一個(gè)單獨(dú)的文件里,這樣會(huì)很容易實(shí)現(xiàn)對(duì)類(lèi)進(jìn)行復(fù)...
    王興伍閱讀 569評(píng)論 0 0
  • 在PHP開(kāi)發(fā)過(guò)程中,如果希望從外部引入一個(gè)class,通常會(huì)使用include和require方法,去把定義這...
    四月不見(jiàn)閱讀 1,135評(píng)論 0 0
  • 一 預(yù)定義接口 1.1 遍歷 Traversable(遍歷)接口 檢測(cè)一個(gè)類(lèi)是否可以被foreach遍歷,該接口不...
    coderhu閱讀 1,307評(píng)論 0 0
  • 本文分為兩部分:第一部分講__autoload()函數(shù)實(shí)現(xiàn)的類(lèi)自動(dòng)加載。第二部分講spl_autoload_reg...
    舒小賤閱讀 2,646評(píng)論 1 4
  • 小小說(shuō):副局長(zhǎng)來(lái)視察 金 木 我們這兒本來(lái)只是一個(gè)鎮(zhèn),為了招商引資的需要,愣是升格為一個(gè)縣級(jí)新區(qū),很自然,原來(lái)的一...
    金木文學(xué)世界閱讀 197評(píng)論 0 0

友情鏈接更多精彩內(nèi)容