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';
}
}
?>