PHP自動加載

   咱們在PHP的項目開發與學習中,若是要引入外部的class文件,通常咱們會使用require,include,require_once,include_once來手動加載到相應的目錄。當咱們進行小項目開發,或者學習階段這種方法沒有一點問題。可是若是進行大項目開發或者寫一個框架那麼再用這種方法就不行了,例如要加載1000個類就要include 1000次,若是是框架,有些類是根據用戶的須要動態的加載的,因此這種方法不可取,而且太多的include操做會下降性能,並且不利於維護。php

    PHP5在自動加載PHP類時,若是類不存在,或者沒有使用iclude包含進來,PHP都會出錯,Zend引擎會自動調用系統內置的魔術函數__autoload()函數,可是須要本身寫這個函數,PHP5.2以及更高的版本後,可使用spl_autoload_register函數自定義自動加載處理函數。當沒有調用此函數,默認狀況下會使用SPL自定義的spl_autoload函數。
例如在TP中的自動加載應用:
 
 
注意:在CLI模式下運行PHP腳本的話__autoload()無效;
 
要理解自動加載叫首先要了解這幾個函數
1 spl_autoload() ;
2 spl_autoload_call() ;
3 spl_autoload_register() ;
說以前以前仍是有必要了解SPL :
    spl 是Standard PHP Library(標準PHP庫)的縮寫。是PHP5引入的一個擴展庫,主要功能包括autoload機制的實現及包括各類Iterator接口或類。 SPL autoload機制的實現是經過將函數指針autoload_func指向本身實現的具備自動裝載功能的函數來實現的。SPL有兩個不一樣的函數 spl_autoload, spl_autoload_call,經過將autoload_func指向這兩個不一樣的函數地址來實現不一樣的自動加載機制。
 
1:spl_autoload() 

    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函數

3:spl_autoload_register() 註冊__autoload()函數 
    spl_autoload_register()函數是主流框架使用最多的也是很是核心的函數之一,可實現自動註冊函數和類,實現相似__autoload() 函數功能,簡化了類的調用與加載,提升了工做的效率
注意:若是加載的文件包含函數,使用則必定須要實例化裏面的類,不然就產生異常狀況 Call to undefined function錯誤。
函數原型:
1 bool spl_autoload_register ([ callback $autoload_function ] ) 
 
    將函數註冊到SPL __autoload函數棧中。若是該棧中的函數還沒有激活,則激活它們。 若是在你的程序中已經實現了__autoload函數,它必須顯式註冊到__autoload棧中。由於 spl_autoload_register()函數會將Zend Engine中的__autoload函數取代爲spl_autoload() spl_autoload_call()。 參數  autoload_function 欲註冊的自動裝載函數。若是沒有提供任何參數,則自動註冊autoload的默認實現函數 spl_autoload()。 
    若是須要多條 autoload 函數,spl_autoload_register() 知足了此類需求。 它實際上建立了 autoload 函數的隊列,按定義時的順序逐個執行。相比之下, __autoload() 只能夠定義一次。
 
總結:

    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 ?>
相關文章
相關標籤/搜索