詳細介紹php自動載入原理

王林
發布: 2023-02-23 14:40:02
原創
5371 人瀏覽過

詳細介紹php自動載入原理

說起PHP的自動加載,很多同學可能都會想到各種框架的自動加載功能,PHP規範中的PSR0和PSR4原則,Composer的自動加載功能等等,這些都為我們的開發提供了很大的方便。

那麼PHP自動載入的前因後果到底是什麼? PHP的內部原理又是怎麼樣的呢?接下來我就根據自己的理解來進行分析總結:

為什麼會有自動載入?

在PHP物件導向(OO)程式設計中,為了方便管理,我們都會把一個類別寫在一個單獨的檔案中,那麼如果想在A類別中使用B類的功能,就需要把B類載入到A類。對於這樣的需求在最原始的時候,我們是透過require 和 include 語法實現的,這2種語法結果基本上一樣,執行流程有一些區別,這裡不解釋。例如:

//文件 B.php
<?php
class B{
    public function echo_info(){
        echo "我是class B中的方法执行结果";
    }
}
?>
//文件 A.php
<?php
require &#39;b.php&#39;;//include &#39;b.php&#39;;
class A{
    public function test(){
        $b_object = new B();
        $b_object->echo_info();
    }
}
$a_object = new A();
$a_oject->test();
?>
命令行输入:#php a.php
    输出: “我是class B中的方法执行结果“
登入後複製

於是,PHP5實作了類別的自動載入(Autoload)功能,這個功能最初是透過PHP的一個魔術方法__autoload()實現的。後來,PHP擴充SPL(Standard PHP Library 標準PHP類別函式庫)又實作了更強大的自動載入機制。

php原始自動載入

#首先,先介紹下__autoload()方法。還是剛剛的例子,使用__autoload()可以做如下修改:

//文件 B.php 不做修改
//文件 A.php
<?php
class A{
    public function test(){
        $b_object = new B();
        $b_object->echo_info();
    }
}
function __autoload($classname){
    require $classname.&#39;.php&#39;;//include &#39;b.php&#39;;
}
$a_object = new A();
$a_oject->test();
?>
命令行输入:#php a.php
    输出: “我是class B中的方法执行结果“
登入後複製

我們在A文件中加了一個函數:__autoload(),並且自己在函數中編寫了相應的引入方法,運行之後同樣得到了結果,沒有報錯。我們需要明確__autoload()函數PHP在找不到類別的時候會自動執行,但是PHP內部並沒有定義這個函數,這個函數需要開發著自己定義,並且編寫內部邏輯,PHP只負責在需要的時候自動調用執行。而且在呼叫的時候會自動傳人要載入的類別名稱作為參數。

有了__autoload()函數,可以看出,如果我們現在需要引入100個其它文件,只需要訂好一個規則,編寫一個函數就可以了。這比直接用require/inlude有了很大進步,但是同樣也有新的問題,在一個專案中,我們只能寫一個__autoload()函數,如果專案比較大,載入每個檔案都使用相同的規則顯然是不切實際的,那麼我們可能需要在__autoload()中編寫複雜的規則邏輯來滿足載入不同檔案的需求。這同樣會使得__autoload()函數變得複雜臃腫,難以維持管理。

於是,SPL(Standard PHP Library 標準PHP類別函式庫)的自動載入機制就應時而生了。

SPL自動載入

#首先,明確一點,PHP在實例化一個物件時(實際上在實現接口,使用類別常數或類別中的靜態變量,調用類別中的靜態方法時都會如此),首先會在系統中查找該類別(或接口)是否存在,如果不存在的話就嘗試使用autoload機制來加載該類。而autoload機制的主要執行過程為:

1、檢查執行器全域變數函數指標autoload_func是否是NULL;

2.如果autoload_func==NULL ,則查找系統是否定義__autoload() 函數,如果定義了,則執行並傳回載入結果。如果沒有定義,則報錯並退出;

3、如果 autoload_func 不等於NULL,則直接執行 autoload_func 指向的函數載入類別,此時並沒有檢查 __autoload() 函數是否定義。

透過對PHP自動載入流程的了解,可以看到PHP實際上提供了兩種方法來實現自動裝載機制:

一種我們前面已經提到過,是使用用戶定義的__autoload()函數,這通常在PHP原始程式中來實現;

另外一種是設計一個函數,將autoload_func指標指向它,這通常使用C語言在PHP擴充中實現,即SPL autoload機制。

如果兩種方式都實作了,也就是 autoload_func 不等於NULL,程式只會執行第二種方式,__autoload() 函數是不會被執行的。

先看一個SPL 自動載入範例:

B.php文件不变
A.php
<?php
class A{
    public function test(){
        $b_object = new B();
        $b_object->echo_info();
    }
}

function __autoload($classname){
    require $classname.&#39;.php&#39;;//include &#39;b.php&#39;;
}

function my_autoload($classname){
    require $classname.&#39;.php&#39;;//include &#39;b.php&#39;;
    echo &#39;my_autoload   &#39;;
}

spl_autoload_register(&#39;my_autoload&#39;);
$a_object = new A();
$a_object->test();

结果:my_autoload  我是class B中的方法执行结果
?>
登入後複製

在這個小例子,可以看到,透過spl_autoload_register('my_autoload'),實作了當程式執行找不到類別B時,會執行自訂的my_autoload()函數,載入B類。實際上 spl_autoload_register(’my_autoload’) 的作用就是 把autoload_func 指標指向 my_autoload()。現在,整個PHP 自動載入過程就明白了。

詳細分析SPL自動載入過程

#首先還是剛剛的小例子,假如把spl_autoload_register('my_autoload') 改成spl_autoload_register()不添加任何參數,B類能被載入嗎?答案是:YES。 

為什麼呢?

因为SPL扩展内部自己定义了一个自动加载函数 spl_autoload(),实现了自动加载的功能,如果我们不定义自己的自动加载函数,并且程序里写了 spl_autoload_register()(如果不传参数,必须是第一次执行才会有效)或者 spl_autoload_register(’spl_autoload’),那么autoload_func 指针就会指向内部函数 spl_autoload()。程序执行的时候如果找不到相应类就会执行该自动加载函数。

那么,SPL 是怎么实现autoload_func 指针指向不同的函数呢?

原来,在SPL内部定义了 一个函数 spl_autoload_call() 和 一个全局变量autoload_functions。autoload_functions本质上是一个HashTable,不过我们可以将其简单的看作一个链表,链表中的每一个元素都是一个函数指针,指向一个具有自动加载类功能的函数。

spl_autoload_call()的作用就是按顺序遍历 autoload_functions,使得autoload_func指向每个自动加载函数,如果加载成功就停止,如果不成功就继续遍历下个自动加载函数,直到加载成功或者遍历完所有的函数。

那么,autoload_functions 这个列表是谁来维护的呢?就是 spl_autoload_register() 这个函数。我们说的自动加载函数的注册,其实就是通过spl_autoload_register()把自动加载函数加入到 autoload_functions 列表。

到此为止,整个自动加载的流程就是分析结束了。

  相关SPL自动加载函数:
  spl_autoload_functions() //打印autoload_functions列表
  spl_autoload_unregister() //注销自动加载函数
登入後複製

以上便是php自动加载原理的全部介绍,想了解更多相关内容请访问PHP中文网:PHP视频教程

以上是詳細介紹php自動載入原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!