在巢狀迴圈中,如何精確跳出指定層級是常見需求。PHP 的 break 支援可選參數 N,指定跳出的層數,但使用不當易導致邏輯錯誤。本文詳細解析機制與最佳實踐。
<?php
// 迴圈層級由「內而外」遞增計數
for ($i = 0; $i < 3; $i++) { // 第 3 層(最外層)
foreach (range(1,3) as $v1) { // 第 2 層
foreach (range(1,3) as $v2) { // 第 1 層(最內層)
echo "第 1 層迴圈<br>";
break 2; // 跳出第 2 層(即跳出中間的 foreach)
}
echo "第 2 層迴圈<br>"; // 不會執行
}
echo "第 3 層迴圈<br>"; // 正常執行
}
// 輸出:
// 第 1 層迴圈
// 第 3 層迴圈
// 第 1 層迴圈
// 第 3 層迴圈
// 第 1 層迴圈
// 第 3 層迴圈
?>
break 等同 break 1,僅跳出當前迴圈。break N 的 N 為正整數,表示向外跳出的層數。for、foreach、while、do-while、switch)。switch 視為一層,break 2 可跳出包含 switch 的外層迴圈。<?php
// 錯誤:以為 break 2 跳出兩個 foreach,實際包含外層 for
for ($i=0; $i<2; $i++) {
foreach (range(1,2) as $a) {
foreach (range(1,2) as $b) {
if ($b === 2) break 2; // 實際跳出中間 foreach + 外層 for!
}
}
}
// 結果:外層 for 只執行一次
?>
<?php
$shouldBreakOuter = false;
for ($i=0; $i<3 && !$shouldBreakOuter; $i++) {
foreach (range(1,3) as $v1) {
foreach (range(1,3) as $v2) {
if ($v2 === 2) {
$shouldBreakOuter = true;
break; // 只跳出當層
}
}
if ($shouldBreakOuter) break;
}
}
?>
<?php
function processData() {
for ($i=0; $i<3; $i++) {
foreach (range(1,3) as $v1) {
foreach (range(1,3) as $v2) {
if ($v2 === 2) return; // 直接結束整個函數
}
}
}
}
?>
<?php
for ($i=0; $i<3; $i++) {
foreach (range(1,3) as $v1) {
foreach (range(1,3) as $v2) {
if ($v2 === 2) goto END_LOOPS;
}
}
}
END_LOOPS:
echo '已跳出所有迴圈';
?>
| 方案 | 可讀性 | 效能 | 適用場景 |
|---|---|---|---|
break N | 中(需心算層級) | 最高 | 簡單巢狀、層級固定 |
| 旗標變數 | 高(意圖明確) | 極微小開銷 | 複雜邏輯、團隊協作 |
| 函數 return | 最高(結構清晰) | 函數呼叫開銷 | 獨立業務邏輯單元 |
| goto | 低(破壞結構化) | 最高 | 極度效能敏感、舊代碼維護 |
break N 是 PHP 獨特且強大的功能,但「層級計算包含 switch」與「內外層計數反直覺」是兩大坑點。現代 PHP 開發推薦使用旗標變數或函數封裝,以清晰的控制流換取極微的效能差異,降低維護成本。