spl_autoload_register() 是 PHP 5.1.2+ 官方推薦的自動載入機制,取代已棄用的 __autoload(),支援多載入器堆疊、類別方法、靜態方法與匿名函式。本文從原理到進階應用,完整剖析 SPL 自動載入生態。
function __autoload($class) {
$file = $class . '.class.php';
if (is_file($file)) require_once $file;
}
$obj = new PRINTIT(); // 自動觸發 __autoload('PRINTIT')
缺點:全域僅能存在一個,無法模組化、無法協同第三方庫。
function loadPrint($class) {
$file = $class . '.class.php';
if (is_file($file)) require_once $file;
}
spl_autoload_register('loadPrint'); // 註冊載入器
$obj = new PRINTIT(); // 觸發 loadPrint('PRINTIT')
| 類型 | 註冊寫法 | 適用場景 |
|---|---|---|
| 函式名稱 | spl_autoload_register('myLoader') | 簡單專案、單一載入邏輯 |
| 類別靜態方法 | spl_autoload_register(['MyLoader', 'load']) 或 'MyLoader::load' | 封裝邏輯、單例模式 |
| 物件實例方法 | spl_autoload_register([$loaderObj, 'load']) | 需保持狀態的載入器 |
| 匿名函式 | spl_autoload_register(function($class){ ... }) | 臨時、閉包封裝 |
spl_autoload_register(function($class) {
// 1. 核心庫優先
if (str_starts_with($class, 'Core\\')) {
$file = __DIR__ . '/core/' . str_replace('\\', '/', $class) . '.php';
if (is_file($file)) return require $file;
}
});
spl_autoload_register(function($class) {
// 2. 應用層
$file = __DIR__ . '/app/' . str_replace('\\', '/', $class) . '.php';
if (is_file($file)) return require $file;
});
spl_autoload_register(function($class) {
// 3. 套件 (vendor) - 通常由 Composer 處理
// 這裡僅示意
});
執行順序:按註冊順序依序嘗試,任一載入成功即停止。若需確保特定載入器優先,請最早註冊。
spl_autoload():預設實作,依 spl_autoload_extensions() 設定的副檔名(預設 .inc, .php)在 include_path 中尋找 類別名.php。spl_autoload_call():遍歷所有已註冊載入器並呼叫。spl_autoload_extensions('.class.php, .interface.php');
set_include_path(get_include_path() . PATH_SEPARATOR . '/my/libs');
spl_autoload_register(); // 註冊預設 spl_autoload
class Autoloader {
public static function init(): self {
static $instance = null;
return $instance ??= new self();
}
private function __construct() {
spl_autoload_register([$this, 'loadModel']);
spl_autoload_register([$this, 'loadController']);
spl_autoload_register([$this, 'loadHelper']);
spl_autoload_register([$this, 'loadLibrary']);
}
private function loadClass(string $class, string $dir, string $suffix): void {
$class = preg_replace('/_' . $suffix . '$/ui', '', $class);
$file = __DIR__ . "/$dir/" . str_replace('_', '/', $class) . ".$suffix.php";
if (is_file($file)) require $file;
}
public function loadModel($class) { $this->loadClass($class, 'model', 'model'); }
public function loadController($class) { $this->loadClass($class, 'controller', 'controller'); }
public function loadHelper($class) { $this->loadClass($class, 'helper', 'helper'); }
public function loadLibrary($class) { $this->loadClass($class, 'lib', 'library'); }
}
// 啟動
Autoloader::init();
新專案請直接使用 Composer PSR-4 自動載入,vendor/autoload.php 內部已封裝 spl_autoload_register:
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/",
"Core\\": "core/"
},
"classmap": ["legacy/"], // 非 PSR-4 舊碼
"files": ["helpers/global.php"] // 函式檔
}
}
執行 composer dumpautoload -o 產生最佳化 classmap,生產環境載入極快。
__autoload 並註冊 spl_autoload_register → __autoload 會失效,需手動 spl_autoload_register('__autoload') 納入堆疊。bool 或靜默處理。spl_autoload_functions() 列出所有已註冊載入器;get_declared_classes() 檢查類別是否已載入。spl_autoload_register 是 PHP 現代自動載入的基石,支援堆疊、優先序、多種呼叫類型。掌握其機制能讓你理解 Composer、框架啟動流程,並能在必要時撰寫客製化載入器。實務上,優先使用 Composer PSR-4,僅在舊系統整合、特殊插件機制時手寫載入器。
相關專題:《PHP 面向對象程序設計入門教程》、《PHP 陣列操作技巧大全》。