自動加載是現代 PHP 組件化、框架化開發的基石。本文梳理從早期 __autoload 到 SPL spl_autoload_register、PSR-0/PSR-4 標準、Composer 生態的演進脈絡。
| 階段 | 機制 | 特點 |
|---|---|---|
| PHP 5.0 | function __autoload($class) | 全局單一函數,無法多庫共存,已棄用 (7.2) 移除 (8.0) |
| PHP 5.1+ | spl_autoload_register($callable) | 支持多個加載器堆棧,優先級可控,標準庫實現 |
| 2009 | PSR-0 | 命名空間映射目錄,下劃線作為目錄分隔符 |
| 2014 | PSR-4 | 優化前綴映射,Vendor\Package\Class → src/Class.php,現代標準 |
| 2012+ | Composer | 依賴管理 + 自動生成 PSR-4 加載器,事實標準 |
class Psr4Loader {
private $prefixes = []; // 前綴 => 基礎目錄[]
public function addPrefix(string $prefix, string $baseDir): void {
$prefix = trim($prefix, '\\') . '\\';
$baseDir = rtrim($baseDir, '/\\') . '/';
$this->prefixes[$prefix][] = $baseDir;
}
public function register(): void {
spl_autoload_register([$this, 'loadClass']);
}
public function loadClass(string $class): void {
foreach ($this->prefixes as $prefix => $dirs) {
if (strncmp($class, $prefix, strlen($prefix)) !== 0) continue;
$relativeClass = substr($class, strlen($prefix));
$fileName = str_replace('\\', '/', $relativeClass) . '.php';
foreach ($dirs as $dir) {
$file = $dir . $fileName;
if (is_file($file)) {
require $file;
return;
}
}
}
}
}
// 使用
$loader = new Psr4Loader();
$loader->addPrefix('App', __DIR__ . '/src');
$loader->addPrefix('Vendor\Package', __DIR__ . '/vendor/package/src');
$loader->register();
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/",
"App\\Tests\\": "tests/"
},
"files": ["src/helpers.php"] // 全局函數文件
},
"autoload-dev": {
"psr-4": { "App\\Tests\\": "tests/" }
}
}
執行 composer dump-autoload -o 生成優化加載器(類映射表),生產環境必用 -o。
composer dump-autoload -o --classmap-authoritative,避免文件系統查找,直接內存映射。opcache.preload=preload.php,將核心類常駐內存。require_once:Composer 加載器內部已處理重複加載,手動 require 反而增加開銷。composer install --no-dev --optimize-autoloader。| 現象 | 原因 | 解決 |
|---|---|---|
| Class not found | 命名空間/目錄不符合 PSR-4 | 檢查 composer.json 前綴映射、目錄大小寫(Linux 區分大小寫) |
| 修改代碼不生效 | OPcache 緩存舊版本 | 重啟 PHP-FPM 或 opcache_reset();開發環境關閉 OPcache |
| 循環依賴 | A 載入時需 B,B 載入時需 A | 重構:提取公共接口、使用依賴注入容器、延遲加載代理 |
現代鐵律:項目啟動即
require __DIR__.'/vendor/autoload.php';,其餘交給 Composer + PSR-4。手寫加載器僅用於理解原理或極簡無依賴項目。