SPL (Standard PHP Library) 從 PHP 5.0 內置,5.3 成熟,提供**接口、迭代器、數據結構、自動載入、異常、文件處理**等標準化組件。它是 PHP 核心擴展,**無需安裝、無需配置、開箱即用**,卻常被開發者忽視。本文系統梳理 SPL 核心能力與實戰應用模式。
| 類別 | 核心類/接口 | 用途 |
|---|---|---|
| 自動載入 | spl_autoload_register() | 註冊多個自動載入器,替代 __autoload |
spl_autoload_unregister() | 移除載入器 | |
spl_autoload_functions() | 獲取已註冊載入器列表 | |
| 迭代器 | Iterator, IteratorAggregate | 自定義可遍歷對象 |
RecursiveIterator, RecursiveIteratorIterator | 遞歸遍歷樹狀結構 | |
FilterIterator, CallbackFilterIterator, RegexIterator | 聲明式過濾 | |
ArrayIterator, ArrayObject | 陣列對象化,支援迭代、訪問器 | |
DirectoryIterator, RecursiveDirectoryIterator, FilesystemIterator | 文件系統遍歷標準化 | |
LimitIterator, NoRewindIterator, InfiniteIterator | 切片、單次遍歷、無限循環 | |
| 數據結構 | SplFixedArray | 固定長度陣列,內存效率高、速度快 |
SplStack, SplQueue, SplHeap, SplPriorityQueue | 棧、隊列、堆、優先隊列 | |
SplDoublyLinkedList | 雙向鏈表,高效插入刪除 | |
SplObjectStorage | 對象集合,支援附加數據、唯一性、引用計數 | |
SplObserver, SplSubject | 觀察者模式標準接口 | |
| 文件處理 | SplFileInfo, SplFileObject | 文件信息查詢、CSV/行讀取、鎖操作 |
| 異常 | LogicException, RuntimeException 等層次化異常 | 語義化錯誤處理 |
src/
if (str_starts_with($class, 'App\\')) {
$file = __DIR__ . '/src/' . str_replace('\\', '/', substr($class, 4)) . '.php';
if (file_exists($file)) require $file;
}
}
}
class VendorLoader {
public static function load($class) {
// 兼容非 PSR-0/4 第三方庫
static $map = [
'LegacyLib' => '/lib/LegacyLib.php',
'OldClass' => '/lib/old/OldClass.class.php',
];
if (isset($map[$class])) require $map[$class];
}
}
// 2. 註冊 (順序決定優先級)
spl_autoload_register(['MyProjectLoader', 'load']);
spl_autoload_register(['VendorLoader', 'load']);
// 3. 可隨時移除不再需要的載入器
// spl_autoload_unregister(['VendorLoader', 'load']);
// 4. 查看已註冊
print_r(spl_autoload_functions());
__autoload 膨脹。getInnerIterator();
return $file->isFile()
&& in_array(strtolower($file->getExtension()), $this->allowedExt);
}
}
// 組合迭代器管道
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('/var/www/uploads', FilesystemIterator::SKIP_DOTS)
);
$filtered = new ImageFilterIterator($iterator);
// 可再組合:限制數量、跳過前 N 個
$limited = new LimitIterator($filtered, 0, 100);
foreach ($limited as $file) {
/** @var SplFileInfo $file */
printf("%s (%d bytes, %s)\n",
$file->getPathname(),
$file->getSize(),
date('Y-m-d H:i:s', $file->getMTime())
);
}
DirectoryIterator → RecursiveIteratorIterator → FilterIterator → LimitIterator,各司其職。ImageFilterIterator 可獨立單元測試。setSize() 但會重新分配)。id = 1;
$user2 = new stdClass(); $user2->id = 2;
// 附加對象與額外數據
$storage->attach($user1, ['role' => 'admin', 'login_at' => time()]);
$storage->attach($user2, ['role' => 'user']);
// 檢查存在性 (O(1) 哈希查找)
var_dump($storage->contains($user1)); // true
// 獲取附加數據
var_dump($storage[$user1]); // ['role'=>'admin', 'login_at'=>...]
// 迭代 (保持插入順序)
foreach ($storage as $user) {
echo "User {$user->id}: {$storage[$user]['role']}\n";
}
// 移除
$storage->detach($user1);
// 觀察者模式內建支援
class Logger implements SplObserver {
public function update(SplSubject $subject) {
echo "Log: " . get_class($subject) . " changed\n";
}
}
$subject = new class implements SplSubject {
private $observers;
public function __construct() { $this->observers = new SplObjectStorage(); }
public function attach(SplObserver $o) { $this->observers->attach($o); }
public function detach(SplObserver $o) { $this->observers->detach($o); }
public function notify() { foreach($this->observers as $o) $o->update($this); }
};
$subject->attach(new Logger());
$subject->notify();
| 場景 | 推薦 SPL 組件 | 收益 |
|---|---|---|
| 大量數值數據存儲/計算 | SplFixedArray | 內存 -70%, 速度 +20% |
| 高頻隊列/棧操作 | SplQueue / SplStack | O(1) 入隊出隊,無陣列重建開銷 |
| 優先級任務調度 | SplPriorityQueue | 堆實現,自動排序,O(log n) 入出 |
| 對象唯一集合/關聯數據 | SplObjectStorage | O(1) 查找,支援附加數據,垃圾回收友好 |
| 文件系統遍歷/過濾/轉換 | RecursiveDirectoryIterator + FilterIterator | 聲明式、流式、可組合、可測試 |
| CSV 大文件逐行處理 | SplFileObject::setFlags(SplFileObject::READ_CSV) | 內存常量級,自動解析 CSV 欄位 |
| 多命名空間自動載入 | spl_autoload_register | 解耦、優先級、動態管理 |
SPL 是 PHP **「瑞士軍刀」**:標準化、高性能、面向對象、可組合。它不學習成本高,但**掌握後能從架構層面提升代碼質量、性能、可維護性**。建議:
__autoload** 為 spl_autoload_register。SPL 不只是庫,是現代 PHP 工程化思維的體現。