五種遍歷方法代碼對比
<?php
$arr = ['a' => 'abc', 'b' => 123, 'c' => true];
// 方法 1:for 迴圈 (需連續數字索引)
echo "1. for:\n";
for ($i = 0; $i < count($arr); $i++) {
echo $arr[$i] . ", ";
}
echo "\n";
// 方法 2:foreach 只取值
echo "2. foreach (value only):\n";
foreach ($arr as $value) {
echo "$value, ";
}
echo "\n";
// 方法 3:foreach 取鍵值 (最常用、推薦)
echo "3. foreach (key => value):\n";
foreach ($arr as $key => $value) {
echo "$key-$value, ";
}
echo "\n";
// 方法 4:while + each() (舊式,PHP 7.2 棄用,8.0 移除)
echo "4. while + each():\n";
reset($arr);
while ($item = each($arr)) {
echo $item['key'] . '-' . $item['value'] . ", ";
}
echo "\n";
// 方法 5:while + list() + each() (同上已移除)
echo "5. while + list():\n";
reset($arr);
while (list($key, $val) = each($arr)) {
echo "$key-$val, ";
}
echo "\n";
?>
效能基準測試 (PHP 8.2, 100萬元素陣列)
<?php
$arr = range(1, 1_000_000);
$iterations = 10;
function bench(string $name, callable $fn) {
$start = hrtime(true);
for ($i=0; $i<$iterations; $i++) $fn($arr);
$ms = (hrtime(true) - $start) / 1e6 / $iterations;
echo "$name: ${ms}ms/iter\n";
}
bench('foreach (val)', fn($a) => foreach($a as $v) {});
bench('foreach (k=>v)', fn($a) => foreach($a as $k=>$v) {});
bench('for loop', fn($a) => { for($i=0;$iv): 14.1ms
for loop: 18.7ms
*/
?>
適用場景選擇指南
| 場景 | 推薦方法 | 理由 |
| 一般遍歷、讀取值 | foreach ($arr as $v) | 語法最簡潔、效能最好、自動處理關聯/索引 |
| 需要鍵名 | foreach ($arr as $k => $v) | 同以上,鍵值同時取得 |
| 需控制索引、跳過、逆序 | for ($i=count()-1; $i>=0; $i--) | 完全控制迴圈變數 |
| 遍歷中刪除元素 | foreach ($arr as $k => $v) { if(...) unset($arr[$k]); } | foreach 在複製上操作,安全刪除 |
| 引用修改原值 | foreach ($arr as &$v) { $v *= 2; } unset($v); | 加 & 修改原陣列,結束後 unset($v) 解除引用 |
| 多維陣列遞迴 | array_walk_recursive() 或自訂遞迴函數 | 統一處理葉子節點 |
現代最佳實踐
<?php
// 1. 箭頭函數配合 array_map/filter/reduce (PHP 7.4+)
$doubled = array_map(fn($x) => $x * 2, $arr);
$evens = array_filter($arr, fn($x) => $x % 2 === 0);
$sum = array_reduce($arr, fn($carry, $x) => $carry + $x, 0);
// 2. 解構賦值 (PHP 7.1+)
foreach ($users as ['id' => $id, 'name' => $name]) {
echo "$id: $name\n";
}
// 3. Generator 記憶體高效處理大資料集
function readLargeCsv(string $path): Generator {
$fh = fopen($path, 'r');
while (($row = fgetcsv($fh)) !== false) {
yield $row;
}
fclose($fh);
}
foreach (readLargeCsv('huge.csv') as $row) {
// 一次只在記憶體保留一行
}
?>
已棄用/移除功能提醒
each():PHP 7.2 棄用,8.0 移除,請改用 foreach
list() 搭配 each() 同理
reset()/next()/current()/key() 內部指標函數雖保留,但極少在現代代碼中直接使用