PHP 提供 foreach、while + list/each、for 三種陣列遍歷方式。直覺認為操作內部指標的 while 最快,但實測證明 foreach 因為是 C 內核原生實現、操作陣列副本(Copy-on-Write),在絕大多數場景下效能顯著優於其他兩種。本文提供完整基準測試代碼、結果分析與選型指南。
<?php
$urls = ['aaa', 'bbb', 'ccc', 'ddd'];
// 1. foreach(推薦)
foreach ($urls as $url) {
echo "URL: $url
";
}
// 2. while + list + each(PHP 7.2 棄用 each,8.0 移除)
while (list($key, $val) = each($urls)) {
echo "URL: $val
";
}
// 3. for 迴圈
for ($i = 0; $i < count($urls); $i++) {
echo "URL: {$urls[$i]}
";
}
?>
<?php
$arr = [];
for ($i = 0; $i < 50000; $i++) {
$arr[] = $i * mt_rand(1000, 9999);
}
function getMicrotime(): float {
[$usec, $sec] = explode(' ', microtime());
return (float)$usec + (float)$sec;
}
// --- for 迴圈 ---
$start = getMicrotime();
for ($i = 0; $i < count($arr); $i++) {
$str = $arr[$i];
}
$forTime = getMicrotime() - $start;
// --- while + each ---
$start = getMicrotime();
while (list($key, $val) = each($arr)) {
$str = $val;
}
$whileTime = getMicrotime() - $start;
// --- foreach ---
$start = getMicrotime();
foreach ($arr as $key => $val) {
$str = $val;
}
$foreachTime = getMicrotime() - $start;
echo "for: " . round($forTime, 7) . "s\n";
echo "while: " . round($whileTime, 7) . "s\n";
echo "foreach: " . round($foreachTime, 7) . "s\n";
?>
for: 0.0228429s while: 0.0544658s foreach: 0.0085628s
| 方式 | 底層機制 | 優勢 | 劣勢 |
|---|---|---|---|
foreach | C 內核原生迴碼,複製陣列指標(COW),單一 opcode 迴圈 | 最快、語法最簡潔、支援物件遍歷、鍵值同時取得 | 修改原陣列需用引用 &$val |
for | 通用迴圈結構,每次 count()、索引存取、邊界檢查 | 可控制步長、倒序、部分遍歷 | 需手動管理索引、count() 應提取到迴圈外 |
while+each | 內部指標移動,each() 函數呼叫開銷大,PHP 8.0 已移除 | 歷史相容性 | 最慢、已棄用、單線程不安全(指標共享) |
$count = count($arr); for ($i=0; $i<$count; $i++) 避免每次呼叫 count()foreach ($arr as &$v) { $v *= 2; } unset($v); 最後 unset 解除引用避免污染array_chunk($arr, 1000) 避免單次迴圈佔用過多 CPU 時間片foreach ($arr as $v) 比 foreach ($arr as $k => $v) 微快foreach 複製整個陣列(記憶體雙倍),大陣列慎用foreach 複製陣列指標(HashTable 指標),Copy-on-Write,記憶體高效each() 棄用each() 移除,foreach 更優化需要修改原陣列值?
├── 是 → foreach ($arr as &$v) { ... } unset($v);
└── 否 → 只需單純遍歷?
├── 是 → foreach ($arr as $v) { ... } // 最快、最簡潔
└── 否 → 需索引控制/步長/倒序?
├── 是 → for ($i=0; $i<$count; $i++) { ... }
└── 否 → foreach ($arr as $k => $v) { ... }
結論:現代 PHP (7.0+) 首選 foreach,兼具效能、可讀性、功能完整性;for 保留給需要索引控制的特殊場景;while+each 已進入歷史博物館。