PHP 7 對 foreach 進行重大底層重寫,改變了內部指針行為、值循環複製語義、引用循環修改可見性等核心機制。本文透過對比實例詳細解析變更內容與遷移注意事項。
$array = [0, 1, 2];
foreach ($array as &$val) {
var_dump(current($array));
}
| 版本 | 輸出 |
|---|---|
| PHP 5 | int(1) int(2) bool(false)(指針隨循環移動) |
| PHP 7 | int(0) int(0) int(0)(指針保持在首元素) |
影響:循環中依賴 current()、next()、reset() 等指針函數的代碼邏輯將改變。
$array = [0, 1, 2];
$ref = &$array; // 觸發複製行為
foreach ($array as $val) {
var_dump($val);
unset($array[1]); // 循環中刪除元素
}
| 版本 | 輸出 |
|---|---|
| PHP 5 | 0 2(第2元素被跳過) |
| PHP 7 | 0 1 2(遍歷原始副本,刪除不影響循環) |
核心機制:PHP 7 值循環時對陣列進行「複製時寫入」(COW)副本,循環迭代器綁定副本,原陣列修改不影響迭代。
$array = [0];
foreach ($array as &$val) {
var_dump($val);
$array[1] = 1; // 循環中追加元素
}
| 版本 | 輸出 |
|---|---|
| PHP 5 | int(0)(新元素不參與循環) |
| PHP 7 | int(0) int(1)(新元素納入迭代) |
PHP 7 優化了引用循環的位置維護,動態增減元素即時反映於迭代器。
對非 Traversable 物件(未實作 Iterator/IteratorAggregate)的循環,無論 by-value 或 by-reference,行為與引用陣列循環一致,位置管理更精確。
實作 Iterator 或 IteratorAggregate 介面的物件,foreach 行為與 PHP 5 一致,由物件內部迭代器完全控制。
current()/next()/key() 等指針函數foreach 關鍵業務邏輯| 場景 | PHP 5 | PHP 7 |
|---|---|---|
| 內部指針 | 隨循環移動 | 保持不變 |
| 值循環修改原陣列 | 影響循環 | 不影響(遍歷副本) |
| 引用循環追加元素 | 不納入循環 | 納入循環 |
| 普通物件循環 | 行為不一致 | 統一為引用語義 |
| Traversable物件 | 由迭代器控制 | 保持不變 |