參考連結:
1、spl_autoload_register與autoload的區別詳解
2、php.net 自動載入類別
很多開發者寫物件導向的應用程式時對每個類別的定義建立一個 PHP 原始檔。一個很大的煩惱是必須在每個腳本開頭寫一個長長的包含檔案清單(每個類別一個檔案)。
在 PHP 5 中,不再需要這樣了。可以定義一個 __autoload() 函數,它會在試圖使用尚未定義的類別時自動呼叫。透過呼叫此函數,腳本引擎在 PHP 出錯失敗前有了最後一個機會載入所需的類別。
簡單的引入範例:
先新建一個類別檔案MyClass.class.php:
<?php class MyClass { public function __construct() { echo "This is MyClass's construct"; } }
再在同目錄下新建任意名字的php檔案:
<?php function __autoload($cls){ var_dump($cls); require './'.$cls.".class.php"; } $o1 = new MyClass(); // 这里不会再执行__autoload了,因为这个类已经require进来了。只有在当前文件中找不到该类的时候才会调用__autoload函数 $o2 = new MyClass();
這裡將require的內容放在了__autoload()中,如果沒有定義這個函數,會報一個致命錯誤(Fatal),提示找不到MyClass類別。
而定義了這個魔術方法會在new一個物件且在當前程式碼中找不到這個類別定義的時候(滿足以上2個條件),__autoload()函數被傳入一個類別名稱參數,並執行函數代碼段。
所以,在函數中執行了var_dump("MyClass");和require './MyClass.class.php';
結果如下:
string(7) "MyClass" This is MyClass's constructThis is MyClass's construct
這裡輸出了一次var_dump的內容和兩次建構子echo的內容。可以證明,當require進來之後,再次new MyClass這個類,並不會再呼叫__autoload()函數。
autoload有缺點:不能重複定義(PHP語言的特徵),導致如果要進行團隊開發的時候很不方便,容易出現衝突。
於是PHP 5.1.2之後有一個autoload註冊函數spl_autoload_register,以下是此函數的一些說明:
將函數註冊到SPL __autoload函數佇列。如果該隊列中的函數尚未激活,則激活它們。
如果需要多個 autoload 函數,spl_autoload_register() 滿足了這類需求。 它實際上創建了 autoload 函數的佇列,按定義時的順序逐一執行。相較之下, __autoload() 只可以定義一次。
在PHP 5.3引入了命名空間之後,此函數的參數有多種形式:
spl_autoload_register('my_autoloader'); // my_autoloader是一个函数名 spl_autoload_register(array('Loader', 'loadClass')); // 表示类内的静态方法,Loader::loadClass // 或者,自 PHP 5.3.0 起可以使用一个匿名函数 spl_autoload_register(function ($class) { include 'classes/' . $class . '.class.php'; }); spl_autoload_register(__NAMESPACE__ .'\Foo::test'); // 自 PHP 5.3.0 起,可以使用命名空间的形式
這個函數只需要在new物件之前呼叫即可。
以下是一個例子(測試以上4種形式):
<?php // namespace Atl; // 加了这句话报错了! function my_autoloader($cls){ echo "<br/>$cls - my_autoloader <br/>"; require_once './MyClass1.class.php'; } class Loader{ public static function loadClass($cls){ echo "<br/>$cls - Loader::loadClass <br/>"; require_once './MyClass2.class.php'; } public static function nspClass($cls){ echo "<br/>$cls - Loader::nspClass <br/>"; require_once './MyClass3.class.php'; } } spl_autoload_register('my_autoloader'); $o1 = new MyClass1(); spl_autoload_register(array('Loader', 'loadClass')); $o2 = new MyClass2(); // 版本检测 if(version_compare(PHP_VERSION, '5.3.0', '<')) die("以下的两个测试需要PHP 5.3及以上"); spl_autoload_register(__NAMESPACE__ .'\Loader::nspClass'); $o3 = new MyClass3(); spl_autoload_register(function ($cls) { echo "<br/>$cls - anonymous function <br/>"; require_once './MyClass4.class.php'; }); $o4 = new MyClass4();
輸出的結果如下(注意到查找的先後順序與註冊順序相同):
MyClass1 - my_autoloader This is MyClass1's construct MyClass2 - my_autoloader MyClass2 - Loader::loadClass This is MyClass2's construct MyClass3 - my_autoloader MyClass3 - Loader::loadClass MyClass3 - Loader::nspClass This is MyClass3's construct MyClass4 - my_autoloader MyClass4 - Loader::loadClass MyClass4 - Loader::nspClass MyClass4 - anonymous function This is MyClass4's construct