您不應該在自動載入器內使用 require_once,因為如果找不到類別,它就不會嘗試使用自動載入器來尋找它。
只需使用 require(),這在效能上會更好,因為它不必檢查是否唯一。
許多撰寫物件導向應用程式的開發人員會為每個類別定義建立一個 PHP 原始碼檔案。最大的困擾之一是在每個指令碼的開頭都必須撰寫一長串所需的 include 陳述式(每個類別一個)。
spl_autoload_register() 函式可以註冊任意數量的自動載入器,讓目前未定義的類別和介面能夠自動載入。透過註冊自動載入器,PHP 在因錯誤而失敗之前,有最後一次機會載入類別或介面。
任何類別式的結構都可以用相同的方式自動載入。這包括類別、介面、特性和列舉。
在 PHP 8.0.0 之前,可以使用 __autoload() 來自動載入類別和介面。然而,它是一個不如 spl_autoload_register() 靈活的替代方案,並且 __autoload() 已在 PHP 7.2.0 中被棄用,並在 PHP 8.0.0 中被移除。
備註:
可以多次呼叫 spl_autoload_register() 來註冊多個自動載入器。然而,從自動載入函式中拋出例外會中斷該過程,並且不允許後續的自動載入函式運行。因此,強烈建議不要從自動載入函式中拋出例外。
範例 #1 自動載入範例
此範例嘗試分別從檔案 MyClass1.php 和 MyClass2.php 載入類別 MyClass1
和 MyClass2
。
<?php
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
});
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
範例 #2 其他自動載入範例
此範例嘗試載入介面 ITest
。
<?php
spl_autoload_register(function ($name) {
var_dump($name);
});
class Foo implements ITest {
}
/*
string(5) "ITest"
致命錯誤:找不到介面 'ITest' 於 ...
*/
?>
範例 #3 使用 Composer 的自動載入器
» Composer 會產生一個 vendor/autoload.php
檔案,該檔案設定為自動載入由 Composer 管理的套件。透過引入此檔案,即可使用這些套件,而無需任何額外的工作。
<?php
require __DIR__ . '/vendor/autoload.php';
$uuid = new Ramsey\Uuid\Uuid::uuid7();
echo "產生新的 UUID -> ", $uuid->toString(), "\n";
?>
您不應該在自動載入器內使用 require_once,因為如果找不到類別,它就不會嘗試使用自動載入器來尋找它。
只需使用 require(),這在效能上會更好,因為它不必檢查是否唯一。
這是我的 PSR-4 類別的自動載入器。我更喜歡使用 Composer 的自動載入器,但這適用於無法使用 Composer 的舊專案。
<?php
/**
* 簡單的自動載入器,因此我們不需要僅為此使用 Composer。
*/
class Autoloader
{
public static function register()
{
spl_autoload_register(function ($class) {
$file = str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file)) {
require $file;
return true;
}
return false;
});
}
}
Autoloader::register();
在撰寫本文時,PHP 不支援自動載入純函式。然而,有一種簡單的方法可以欺騙自動載入器來做到這一點。唯一需要的是,自動載入器從它所經過的檔案中找到搜尋的類別(或任何其他可自動載入的程式碼),並且整個檔案將被包含在執行時期中。
假設您有一個要自動載入的函式的命名空間檔案。只需在該檔案中新增一個具有單一常數屬性的同名類別,就足以觸發自動載入器搜尋該檔案。然後可以透過存取常數屬性來觸發自動載入。
常數可以由任何靜態屬性或方法或預設建構函式取代。然而,我個人覺得名為「load」的常數既優雅又具有資訊性。畢竟這是一個解決方法。另一件要記住的事情是,這會在執行時期引入一個不必要的類別。這樣做的好處是不需要透過路徑手動 include 或 require 包含函式的檔案,進而使程式碼維護更容易。這種行為使得更改專案結構更容易,因為不需要修復手動 include。只有自動載入器需要能夠找到移動的檔案,而這可以自動化。
包含函式的程式碼檔案。
/Some/Namespace/Functions.php
<?php
namespace Some\Namespace;
class Functions { const load = 1; }
function a () {
}
function b () {
}
?>
觸發包含函式的檔案的自動載入。
main.php
<?php
\Some\Namespace\Functions::load;
a();
b();
?>
因為靜態類別沒有建構子,所以我使用這個來初始化這些類別。
當您第一次使用該類別時,將會呼叫 init 函式(如果有的話)。
該類別之前不能被引入,否則由於未使用自動載入,init 函式將不會被呼叫。
<?php
function __autoload($class_name)
{
require_once(CLASSES_PATH.$class_name.'.cls.php');
if(method_exists($class_name,'init'))
call_user_func(array($class_name,'init'));
return true;
}
?>
例如,我用它來按需建立 mysql 連線。
也可以透過將這些行添加到函式中來添加解構子
<?php
if(method_exists($class_name,'destruct'))
register_shutdown_function(array($class_name,'destruct'));
?>