php5后,引入了__autoload這個攔截器方法,可以自動對class文件進行包含引用,通常我們會這么寫,代碼如下:
- function __autoload($classname) {
- include_once $classname . '.class.php';
- }
- $user = new user();
當php引擎試圖實例化一個未知類的操作時,會調用__autoload()方法,在php出錯失敗前有了最后一個機會加載所需的類,因此,上面的這段代碼執行時,php引擎實際上替我們自動執行了一次__autoload方法,將user.class.php這個文件包含進來.
在__autoload函數中拋出的異常不能被catch語句塊捕獲并導致致命錯誤,如果使用 php的cli交互模式時,自動加載機制將不會執行.
當你希望使用pear風格的命名規則,例如需要引入user/register.php文件,也可以這么實現,代碼如下:
- //加載我
- function __autoload($classname) {
- $file = str_replace('_', directory_separator, $classname);
- include_once $file . 'php';
- }
- $userregister = new user_register();
這種方法雖然方便,但是在一個大型應用中如果引入多個類庫的時候,可能會因為不同類庫的autoload機制而產生一些莫名其妙的問題,在php5引入spl標準庫后,我們又多了一種新的解決方案,spl_autoload_register()函數.
此函數的功能就是把函數注冊至spl的__autoload函數棧中,并移除系統默認的__autoload()函數,一旦調用spl_autoload_register()函數,當調用未定義類時,系統會按順序調用注冊到spl_autoload_register()函數的所有函數,而不是自動調用__autoload()函數,下例調用的是user/register.php而不是user_register.class.php,代碼如下:
- //不加載我
- function __autoload($classname) {
- include_once $classname . '.class.php';
- }
- //加載我
- function autoload($classname) {
- $file = str_replace('/', directory_separator, $classname);
- include_once $file . '.php';
- } //開源代碼Vevb.com
- //開始加載
- spl_autoload_register('autoload');
- $userregister = new user_register();
在使用spl_autoload_register()的時候,我們還可以考慮采用一種更安全的初始化調用方法,代碼如下:
- //系統默認__autoload函數
- function __autoload($classname) {
- include_once $classname . '.class.php';
- }
- //可供spl加載的__autoload函數
- function autoload($classname) {
- $file = str_replace('_', directory_separator, $classname);
- include_once $file . '.php';
- } //開源代碼Vevb.com
- //不小心加載錯了函數名,同時又把默認__autoload機制給取消了……
- spl_autoload_register('_autoload', false);
- //容錯機制
- if(false === spl_autoload_functions()) {
- if(function_exists('__autoload')) {
- spl_autoload_register('__autoload', false);
- }
- }
php autoload與include性能比較
p為1000時,腳本耗時約0.076701879501343秒.
如果我們用autoload實現呢?代碼如下:
- #file:php_autoload.php
- function __autoload($class_name) {
- include_once $class_name . '.php';
- }
- for($i = 0;$i < $loop;$i++) {
- new simpleclass();
- }
在這段代碼中,我定義了__autoload函數,幾乎一樣的腳本,當$loop為1時,耗時0.0002131462097168秒,而當$loop為1000時,耗時僅為前面代碼的1/7,0.012391805648804秒.
但請注意看simpleclass的代碼,其中輸出了一行字符串,如果去掉這行輸出后再比較,會是什么樣的結果呢?
在$loop同為1000的情況下,前者耗時0.057836055755615秒,而使用了autoload后,僅僅0.00199294090271秒,效率相差近30倍.
從上面的測試可以看出,當文件僅僅被include一次,autoload會消耗稍微多一點的時間,但如果在文件被反復include的情況下,使用autoload則能大大提高系統性能.
新聞熱點
疑難解答