PHP 內部為每個數組維護一個「指針」(指向當前元素)。foreach 底層正是通過移動此指針實現遍歷。掌握指針操作函數,可實現:逆序遍歷、步長控制、條件跳轉、多指針協作等高級模式,且無需創建副本,內存效率極高。
| 函數 | 作用 | 返回值 | 指針移動 |
|---|---|---|---|
| current() | 取當前元素值 | 值 / false | 不動 |
| key() | 取當前鍵名 | 鍵 / null | 不動 |
| next() | 指針後移 1 位 | 新值 / false | 後移 |
| prev() | 指針前移 1 位 | 新值 / false | 前移 |
| reset() | 指針重置到首元素 | 首值 / false | 歸零 |
| end() | 指針移至尾元素 | 尾值 / false | 跳尾 |
| each() | 取當前鍵值對並後移 | [key,value,0,1] / false | 後移 |
$arr = ['你','若','安','好','便','是','晴','天'];
for (reset($arr); $val = current($arr); next($arr)) {
echo $val . '
';
}
// 輸出: 你 若 安 好 便 是 晴 天
reset($arr);
while ($val = current($arr)) {
echo $val . '
';
next($arr); next($arr); // 移動兩步
}
// 輸出: 你 安 便 晴
reset($arr);
$forward = true;
while ($val = current($arr)) {
echo $val . '
';
if ($forward) { next($arr); next($arr); $forward = false; }
else { prev($arr); $forward = true; }
}
// 輸出: 你 安 若 好 安 便 好 是 便 晴 是 天 晴
end($arr);
while ($val = current($arr)) {
echo $val . '
';
prev($arr);
}
// 輸出: 天 晴 是 便 好 安 若 你
$arr = ['你','若',0,'好']; // 含 0
for (reset($arr); $val = current($arr); next($arr)) {
echo $val . '
';
}
// 僅輸出: 你 若 (遇到 0 循環終止)
解決: 使用 key() !== null 作為條件,而非值的真偽。
for (reset($arr); key($arr) !== null; next($arr)) {
$val = current($arr);
echo $val . '
';
}
// 正確輸出所有元素
$arr = [1,2,3];
foreach ($arr as $v) { /* ... */ }
echo current($arr); // 1 (指針未動)
PHP 7+ foreach 複製數組迭代,不干擾原指針;PHP 5 會移動指針。
$a = [1,3,5,7]; $b = [2,4,6,8];
reset($a); reset($b);
while (key($a)!==null && key($b)!==null) {
$va = current($a); $vb = current($b);
if ($va < $vb) { echo "$va "; next($a); }
else { echo "$vb "; next($b); }
}
// 輸出: 1 2 3 4 5 6 7 8 (歸併排序 merge 步驟)
reset($arr);
while (list($k, $v) = each($arr)) {
echo "$k => $v
";
}
each() 在 PHP 8.0 棄用,建議改用 foreach 或 key()/current()/next() 組合。
面向對象風格,支持多並發迭代器:
$it = new ArrayIterator($arr);
for ($it->rewind(); $it->valid(); $it->next()) {
echo $it->key() . ' => ' . $it->current() . '
';
}
// 可同時創建多個 ArrayIterator 互不干擾
| 方式 | 耗時 | 內存 | 備註 |
|---|---|---|---|
| foreach | ~12ms | ~8MB | 最快,語法糖優化 |
| for + current/next | ~18ms | ~8MB | 函數調用開銷 |
| ArrayIterator | ~22ms | ~10MB | 對象包裝開銷 |
| while + each() | ~35ms | ~8MB | 已棄用,不推薦 |
結論: 常規遍歷首選 foreach;需精確控制指針、逆序、步長、多指針協作時,使用 current/next/prev/end/reset/key 組合。
end($data);
while (($val = current($data)) !== false) {
if ($val['status'] === 'completed') break;
prev($data);
}
$lastCompleted = $val ?? null;
$window = new SplFixedArray(3); // 循環緩衝
$idx = 0;
foreach ($stream as $item) {
$window[$idx] = $item;
$idx = ($idx + 1) % 3;
// 處理窗口內 3 個元素
process($window[0], $window[1], $window[2]);
}
PHP 數組指針是一個強大且被低估的特性。掌握 current/next/prev/end/reset/key 組合,能解決:
✅ 逆序/步長/往復遍歷
✅ 包含 falsy 值的安全遍歷
✅ 雙指針/多指針算法 (歸併、雙端隊列、滑動窗口)
✅ 無需複製數組的就地操作
記住核心原則:用 key() 判斷位置,用 current() 取值,用 next/prev 移動,配合 reset()/end() 定位起點,即可駕馭任意複雜遍歷邏輯。