PHP foreach 迴圈
foreach 是專門用來遍歷陣列和物件的迴圈。它會自動處理索引和元素,是遍歷陣列最簡單、最常用的方式。
基本語法
只取值
foreach ($array as $value) {
// 使用 $value
}
<?php
$fruits = ['蘋果', '香蕉', '橘子'];
foreach ($fruits as $fruit) {
echo "$fruit\n";
}
?>
輸出:
蘋果
香蕉
橘子
取鍵和值
foreach ($array as $key => $value) {
// 使用 $key 和 $value
}
<?php
$fruits = ['蘋果', '香蕉', '橘子'];
foreach ($fruits as $index => $fruit) {
echo "$index: $fruit\n";
}
?>
輸出:
0: 蘋果
1: 香蕉
2: 橘子
遍歷關聯陣列
<?php
$person = [
'name' => 'Alice',
'age' => 25,
'city' => 'Taipei'
];
foreach ($person as $key => $value) {
echo "$key: $value\n";
}
?>
輸出:
name: Alice
age: 25
city: Taipei
傳址修改元素
使用 & 可以直接修改陣列中的元素:
<?php
$numbers = [1, 2, 3, 4, 5];
// 將每個元素乘以 2
foreach ($numbers as &$num) {
$num *= 2;
}
unset($num); // 重要:解除參考
print_r($numbers);
// [2, 4, 6, 8, 10]
?>
使用傳址迴圈後,務必使用 unset() 解除參考,否則可能造成意外的結果:
<?php
$arr = [1, 2, 3];
foreach ($arr as &$val) {
// ...
}
// 忘記 unset($val)
foreach ($arr as $val) {
// $val 仍然是參考,會修改陣列最後一個元素
}
print_r($arr); // [1, 2, 2] - 意外!
?>
遍歷多維陣列
<?php
$users = [
['name' => 'Alice', 'age' => 25],
['name' => 'Bob', 'age' => 30],
['name' => 'Charlie', 'age' => 35],
];
foreach ($users as $user) {
echo "{$user['name']} 是 {$user['age']} 歲\n";
}
?>
輸出:
Alice 是 25 歲
Bob 是 30 歲
Charlie 是 35 歲
巢狀 foreach
<?php
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
foreach ($matrix as $rowIndex => $row) {
foreach ($row as $colIndex => $value) {
echo "[$rowIndex][$colIndex] = $value ";
}
echo "\n";
}
?>
解構賦值 (PHP 7.1+)
在 foreach 中使用解構賦值可以直接取出陣列元素:
<?php
$users = [
['Alice', 25, 'Taipei'],
['Bob', 30, 'Taichung'],
['Charlie', 35, 'Kaohsiung'],
];
foreach ($users as [$name, $age, $city]) {
echo "$name, $age 歲, 住在 $city\n";
}
?>
關聯陣列的解構:
<?php
$users = [
['name' => 'Alice', 'age' => 25],
['name' => 'Bob', 'age' => 30],
];
foreach ($users as ['name' => $name, 'age' => $age]) {
echo "$name 是 $age 歲\n";
}
?>
break 和 continue
break - 跳出迴圈
<?php
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
foreach ($numbers as $num) {
if ($num > 5) {
echo "找到大於 5 的數字,停止迴圈\n";
break;
}
echo "$num ";
}
// 輸出:1 2 3 4 5 找到大於 5 的數字,停止迴圈
?>
continue - 跳過當前迭代
<?php
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
foreach ($numbers as $num) {
// 跳過偶數
if ($num % 2 === 0) {
continue;
}
echo "$num ";
}
// 輸出:1 3 5 7 9
?>
遍歷物件
foreach 可以遍歷物件的公開屬性:
<?php
class Person {
public string $name = 'Alice';
public int $age = 25;
private string $secret = '秘密';
}
$person = new Person();
foreach ($person as $key => $value) {
echo "$key: $value\n";
}
// 只會顯示 public 屬性
// name: Alice
// age: 25
?>
實作 Iterator 介面
自訂類別可以實作 Iterator 介面來支援 foreach:
<?php
class NumberRange implements Iterator {
private int $start;
private int $end;
private int $current;
public function __construct(int $start, int $end) {
$this->start = $start;
$this->end = $end;
}
public function rewind(): void {
$this->current = $this->start;
}
public function current(): int {
return $this->current;
}
public function key(): int {
return $this->current - $this->start;
}
public function next(): void {
$this->current++;
}
public function valid(): bool {
return $this->current <= $this->end;
}
}
$range = new NumberRange(1, 5);
foreach ($range as $index => $value) {
echo "[$index] = $value\n";
}
?>
替代語法
在 HTML 模板中使用替代語法:
<?php $items = ['蘋果', '香蕉', '橘子']; ?>
<ul>
<?php foreach ($items as $item): ?>
<li><?= htmlspecialchars($item) ?></li>
<?php endforeach; ?>
</ul>
實際應用範例
生成 HTML 選單
<?php
$menuItems = [
'home' => '首頁',
'about' => '關於我們',
'products' => '產品',
'contact' => '聯絡我們',
];
$currentPage = 'about';
?>
<nav>
<ul>
<?php foreach ($menuItems as $url => $title): ?>
<li<?= ($url === $currentPage) ? ' class="active"' : '' ?>>
<a href="<?= $url ?>.php"><?= $title ?></a>
</li>
<?php endforeach; ?>
</ul>
</nav>
處理表單輸入
<?php
$_POST = [
'name' => 'Alice',
'email' => 'alice@example.com',
'message' => 'Hello!',
];
$allowedFields = ['name', 'email', 'message'];
$data = [];
foreach ($allowedFields as $field) {
if (isset($_POST[$field])) {
$data[$field] = trim($_POST[$field]);
}
}
print_r($data);
?>
計算總和和平均
<?php
$scores = [85, 92, 78, 96, 88];
$total = 0;
$count = 0;
foreach ($scores as $score) {
$total += $score;
$count++;
}
$average = $total / $count;
echo "總分:$total\n"; // 439
echo "平均:$average\n"; // 87.8
?>
過濾陣列
<?php
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$evens = [];
foreach ($numbers as $num) {
if ($num % 2 === 0) {
$evens[] = $num;
}
}
print_r($evens); // [2, 4, 6, 8, 10]
// 使用 array_filter 更簡潔
$evens = array_filter($numbers, fn($n) => $n % 2 === 0);
?>
轉換陣列
<?php
$users = [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
['id' => 3, 'name' => 'Charlie'],
];
// 建立 id => name 的對應
$userMap = [];
foreach ($users as $user) {
$userMap[$user['id']] = $user['name'];
}
print_r($userMap);
// [1 => 'Alice', 2 => 'Bob', 3 => 'Charlie']
// 使用 array_column 更簡潔
$userMap = array_column($users, 'name', 'id');
?>
合併重複項目
<?php
$orders = [
['product' => 'Apple', 'quantity' => 2],
['product' => 'Banana', 'quantity' => 3],
['product' => 'Apple', 'quantity' => 1],
['product' => 'Orange', 'quantity' => 4],
];
$summary = [];
foreach ($orders as $order) {
$product = $order['product'];
if (!isset($summary[$product])) {
$summary[$product] = 0;
}
$summary[$product] += $order['quantity'];
}
print_r($summary);
// ['Apple' => 3, 'Banana' => 3, 'Orange' => 4]
?>
生成樹狀結構
<?php
$categories = [
['id' => 1, 'name' => '電子產品', 'parent_id' => null],
['id' => 2, 'name' => '手機', 'parent_id' => 1],
['id' => 3, 'name' => '筆電', 'parent_id' => 1],
['id' => 4, 'name' => '服飾', 'parent_id' => null],
['id' => 5, 'name' => '上衣', 'parent_id' => 4],
];
function buildTree(array $items, $parentId = null): array {
$tree = [];
foreach ($items as $item) {
if ($item['parent_id'] === $parentId) {
$children = buildTree($items, $item['id']);
if ($children) {
$item['children'] = $children;
}
$tree[] = $item;
}
}
return $tree;
}
$tree = buildTree($categories);
print_r($tree);
?>