PHP 5 引入 __autoload 魔術函數,嘗試載入未定義的類別;PHP 5.1.2+ 推薦使用 spl_autoload_register 支援多載入器鏈。本文說明兩種機制用法、命名規範對應、最佳實踐與 Composer 整合。
<?php
function __autoload($class) {
// 假設類別檔案命名:class_類別名.php
$file = 'class_' . ucfirst(strtolower($class)) . '.php';
if (file_exists($file)) {
include $file;
}
}
// 使用
$user = new User(); // 自動觸發 __autoload('User') → 載入 class_User.php
$user->name = 'Leon';
$user->printName();
?>
缺點:全域僅能定義一個 __autoload,無法組合多個載入規則。
<?php
// 載入器 1:專案類別
spl_autoload_register(function($class) {
$file = __DIR__ . '/src/' . str_replace('\\', '/', $class) . '.php';
if (file_exists($file)) include $file;
});
// 載入器 2:第三方庫 (PSR-4)
spl_autoload_register(function($class) {
$prefix = 'Vendor\\Package\\';
if (strncmp($class, $prefix, strlen($prefix)) === 0) {
$file = __DIR__ . '/vendor/' . str_replace('\\', '/', substr($class, strlen($prefix))) . '.php';
if (file_exists($file)) include $file;
}
});
// 使用
$obj = new \MyProject\User();
$lib = new \Vendor\Package\Library();
現代 PHP 專案遵循 PSR-4:命名空間前綴對應目錄,類別名對應檔案名。
| 完整類別名 | 命名空間前綴 | 基礎目錄 | 檔案路徑 |
|---|---|---|---|
| Acme\Blog\Post | Acme\Blog\ | /var/www/src | /var/www/src/Post.php |
| Vendor\Pkg\Util | Vendor\Pkg\ | /var/www/vendor | /var/www/vendor/Util.php |
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/",
"Vendor\\Package\\": "vendor/package/src"
}
}
}
執行 composer dump-autoload 產生 vendor/autoload.php,專案入口僅需:
require_once __DIR__ . '/vendor/autoload.php';
Composer 產生的載入器包含 classMap(類別名→檔案路徑陣列),避免 file_exists 磁碟 I/O,大幅提升載入速度。
| 現象 | 原因 | 解決 |
|---|---|---|
| Class not found | 命名空間/目錄對應錯誤 | 檢查 PSR-4 前綴、大小寫、composer dump-autoload |
| 重複載入 | 多載入器皆匹配 | 載入器內加 if (class_exists($class)) return; |
| 效能差 | 大量 file_exists | 使用 classMap、opcache、APCu |
spl_autoload_register 逐步遷移。