天天看點

PHP類的自動加載PHP類的自動加載

PHP類的自動加載

__autoload

PHP在魔術函數__autoload()方法出現以前,如果你要在一個程式檔案中執行個體化100個對象,那麼你必須用include或者require包含進來100個類檔案,或者你把這100個類定義在同一個類檔案中——相信這個檔案一定會非常大。

但是__autoload()方法出來了,以後就不必為此大傷腦筋了,這個類會在你執行個體化對象之前自動加載制定的檔案。

在 PHP 5.3 之前,__autoload 函數抛出的異常不能被 catch 語句塊捕獲并會導緻一個緻命錯誤(Fatal Error)。 自 PHP 5.3 起,能夠 thrown 自定義的異常(Exception),随後自定義異常類即可使用。 __autoload 函數可以遞歸的自動加載自定義異常類。
自動加載不可用于 PHP 的 CLI 互動模式。
如果類名比如被用于 call_user_func(),則它可能包含一些危險的字元,比如 …/。 建議您在這樣的函數中不要使用使用者的輸入,起碼需要在 __autoload() 時驗證下輸入。

如果類存在繼承關系(例如:ClassB extends ClassA),并且ClassA不在ClassB所在目錄

利用__autoload魔術函數執行個體化ClassB的時候就會受到一個緻命錯誤:

解決方法:把所有存在extends關系的類放在同一個檔案目錄下,或者在執行個體化一個繼承類的時候在檔案中手工包含被繼承的類;

./myClass.php
<?php
class myClass {
    public function __construct() {
        echo "myClass init'ed successfuly!!!";
    }
}
?>

./index.php
<?php
// we've writen this code where we need
function __autoload($classname) {
    $filename = "./". $classname .".php";
    include_once($filename);
}

$obj = new myClass();
//myClass init'ed successfuly!!!
           

盡管 __autoload() 函數也能自動加載類和接口,但更建議使用 spl_autoload_register() 函數。 spl_autoload_register() 提供了一種更加靈活的方式來實作類的自動加載(同一個應用中,可以支援任意數量的加載器,比如第三方庫中的)。是以,不再建議使用 __autoload() 函數,

是以 自PHP 7.2.0起,此功能已被 棄用。非常不鼓勵依賴此功能。

spl_autoload_register

spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] ) : bool
           

參數:

autoload_function:

欲注冊的自動裝載函數。如果沒有提供任何參數,則自動注冊 autoload 的預設實作函數spl_autoload()。

throw:

此參數設定了 autoload_function 無法成功注冊時, spl_autoload_register()是否抛出異常。

prepend:

如果是 true,spl_autoload_register() 會添加函數到隊列之首,而不是隊列尾部。

傳回值:

成功時傳回 TRUE, 或者在失敗時傳回 FALSE。

執行個體:

function my_autoloader($class) {
    include  $class . '.class.php';
}

spl_autoload_register('my_autoloader');

// 或者,自 PHP 5.3.0 起可以使用一個匿名函數
spl_autoload_register(function ($class) {
    include  $class . '.class.php';
});
           
<?php

namespace Foobar;

class Foo {
    static public function test($name) {
        print '[['. $name .']]';
    }
}
//spl_autoload_register( array('Foobar\Foo','test') );
spl_autoload_register(__NAMESPACE__ .'\Foo::test'); // 自 PHP 5.3.0 起

 Foo::test('test');//[[test]]
 new test;
 /*
 [[Foobar\test]]
  Fatal error: Uncaught Error: Class 'Foobar\test' not found in...
 */
           

本例抛出一個異常并在 try/catch 語句塊中示範。

spl_autoload_register(function ($name) {
    echo "Want to load $name.\n";
    throw new Exception("Unable to load $name.");
});

try {
    $obj = new NonLoadableClass();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
//Want to load NonLoadableClass.
//Unable to load NonLoadableClass.
           

本例将一個異常抛給不存在的自定義異常處理函數。

<?php
spl_autoload_register(function ($name) {
    echo "Want to load $name.\n";
    throw new MissingException("Unable to load $name.");
});

try {
    $obj = new NonLoadableClass();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
/*
Want to load NonLoadableClass.
Want to load MissingException.

Fatal error: Class 'MissingException' not found in testMissingException.php on line 4
*/
?>
           

加載接口

./index.php
<?php
interface index
{
    public static function test();
}
?>

./test.php
<?php
spl_autoload_register(function ($name) {
    include_once $name.'.php';
});

class Foo implements index {
    static function test(){
        echo 'test';
    }
}
?>