咱們在PHP的項目開發與學習中,若是要引入外部的class文件,通常咱們會使用require,include,require_once,include_once來手動加載到相應的目錄。當咱們進行小項目開發,或者學習階段這種方法沒有一點問題。可是若是進行大項目開發或者寫一個框架那麼再用這種方法就不行了,例如要加載1000個類就要include 1000次,若是是框架,有些類是根據用戶的須要動態的加載的,因此這種方法不可取,而且太多的include操做會下降性能,並且不利於維護。php
1 spl_autoload() ; 2 spl_autoload_call() ; 3 spl_autoload_register() ;
spl_autoload 是SPL實現的默認的自動加載函數,功能比較簡單。有兩個參數,第一個是$class_name,表示類名,第二個參 數$file_extensions是可選的,表示類文件擴展名,能夠在$file_extensions中指定多個擴展名,之間用分號隔開。不指定將使用默認的擴展名.inc或.php。讓spl_autoload自動起做用是將autoload_func指向spl_autoload,方法是使用 spl_autoload_register函數。在PHP腳本中第一次調用spl_autoload_register()時不使用任何參數,就能夠將 autoload_func指向spl_autoload。數組
2:spl_autoload_call()
框架
由spl_autoload() 知道spl_autoload的功能比較簡單,它是在SPL擴展中實現的,沒法擴充它的功能。若是想實現本身的更靈活的自動加載機制就須要使用spl_autoload_call函數。在SPL模塊內部,有一個全局變量autoload_functions,本質上是 一個HashTable,能夠看做一個鏈表,每一個元素都是一個函數指針,指向一個具備自動加載類功能的函數。 spl_autoload_call會按順序執行這個鏈表中每一個函數,在每一個函數執行完成後都判斷一次須要的類是否已經加載, 若是加載成功就直接返回,再也不繼續執行鏈表中的其它函數。若是這個鏈表中全部的函數都執行完成後類尚未加載,spl_autoload_call會直接 退出,並不向用戶報告錯誤。使用了autoload機制,不能保證類就必定能正確的自動加載。在php5中的標準庫方法spl_autoload至關於實現本身的__autoload函數
1 bool spl_autoload_register ([ callback $autoload_function ] )
PHP在實例化一個 對象時(實際上在實現接口,使用類常數或類中的靜態變量等),先會在系統中查找該類(或接口)是否存在,若是不存在的話就 嘗試使用autoload機制來加載該類。性能
autoload機制的主要執行過程爲:學習
1:檢查執行器全局變量函數指針autoload_func是否爲null。 2:若是autoload_func==null, 則查找系統中是否認義有__autoload()函數,若是沒有,則報告錯誤並退出。 3:若是定義了__autoload()函數,則執行__autoload()嘗試加載類,並返回加載結果。 4:若是autoload_func不爲null,則直接執行autoload_func指針指向的函數用來加載類。此時並不檢查__autoload()函數是否認義。
總結以下:ui
自動加載方便了面向對象和代碼複用,可是多個類庫不一樣的__autoload又會致使混亂。能夠用spl_autoload解決,將不一樣開發者的攔截器函數都註冊到自動加載函數的hashtable中。spl實現自動加載的機制是維護一個hashtable,裏面存儲有具備自動加載功能的各個函數。當觸發自動加載機制時,zend會在遍歷執行這個hashtable裏面的函數,直到成功加載類或加載失敗後返回。當須要使用自動加載功能時,使用函數spl_autoload_register()或spl_autoload_register('autoloadfuncitonname')無參的spl_autoload_register()會默認加載spl_autoload()函數,該函數功能有限,只能在inlcude_path中搜索指定擴展名的類庫。有參的spl_autoload_register()默認再也不加載spl_autoload()函數。能夠經過spl_autoload_functions()查看當前自動加載hashtable中的函數,該函數返回一個數組url
注意:使用spl_autoload時,系統會忽略攔截器__autoload,除非顯式地使用spl_autoload_register('__autoload')將其加入hashtablespa
PHP提供了兩種方法來實現自動自動加載,設計
一種是使用用戶定義的__autoload()函數;
1 <?php 2 $file = str_replace("\\", '/', $classname); //能夠開轉換字符 3 function __autoload($className) { 4 if (file_exists($file_url . '.php')) { //先判斷是否存在文件 5 include_once($file_url . '.php'); 6 } 7 } 8 $a = new Acls(); 9 ?>
另一種就是設計一個函數,將autoload_func指針指向它,使用C語言在PHP擴展中實現,即:使用spl自動加載 spl_autoload_register()
1 <?php 2 spl_autoload_register(function($classname){ 3 if($classname){ 4 $file = '../'; 5 $file .= str_replace("\\", '/', $classname); 6 $file .= '.php'; 7 if(file_exists($file)){ 8 include $file; 9 } 10 } 11 }); 12 13 ?>
或者:
1 <?php 2 class Loader { 3 public static function autoload($class) { 4 $path = ''; 5 $path = str_replace('_', '/', $class) . '.php'; 6 include_once($path); 7 } 8 } 9 spl_autoload_register(array('Loader', 'autoload')); 10 ?>