PHP break 與 continue

breakcontinue 是用於控制迴圈流程的語句。break 用於跳出迴圈,continue 用於跳過當前迭代。

break 語句

break 會立即終止迴圈的執行,跳出迴圈區塊:

<?php
for ($i = 1; $i <= 10; $i++) {
    if ($i === 5) {
        echo "到 5 了,跳出迴圈\n";
        break;
    }
    echo "i = $i\n";
}
echo "迴圈結束\n";
?>

輸出:

i = 1
i = 2
i = 3
i = 4
到 5 了,跳出迴圈
迴圈結束

在不同迴圈中使用 break

<?php
// while 迴圈
$count = 0;
while (true) {  // 無限迴圈
    $count++;
    if ($count > 3) {
        break;
    }
    echo "$count ";
}
// 輸出:1 2 3

// foreach 迴圈
$fruits = ['蘋果', '香蕉', '橘子', '葡萄'];
foreach ($fruits as $fruit) {
    if ($fruit === '橘子') {
        break;
    }
    echo "$fruit ";
}
// 輸出:蘋果 香蕉
?>

跳出巢狀迴圈

使用 break n 可以跳出指定層數的迴圈,n 是要跳出的迴圈層數:

<?php
for ($i = 1; $i <= 3; $i++) {
    for ($j = 1; $j <= 3; $j++) {
        echo "($i, $j) ";
        
        if ($i === 2 && $j === 2) {
            echo "\n找到 (2,2),跳出所有迴圈\n";
            break 2;  // 跳出 2 層迴圈
        }
    }
    echo "\n";
}
?>

輸出:

(1, 1) (1, 2) (1, 3) 
(2, 1) (2, 2) 
找到 (2,2),跳出所有迴圈

break 在 switch 中

breakswitch 中用於結束 case 區塊:

<?php
$day = 3;

switch ($day) {
    case 1:
        echo "星期一";
        break;
    case 2:
        echo "星期二";
        break;
    case 3:
        echo "星期三";
        break;  // 沒有 break 會繼續執行下一個 case
    default:
        echo "其他";
}
?>

continue 語句

continue 會跳過當前迭代剩餘的程式碼,直接進入下一次迭代:

<?php
for ($i = 1; $i <= 5; $i++) {
    if ($i === 3) {
        echo "跳過 3\n";
        continue;
    }
    echo "i = $i\n";
}
?>

輸出:

i = 1
i = 2
跳過 3
i = 4
i = 5

跳過偶數

<?php
for ($i = 1; $i <= 10; $i++) {
    // 跳過偶數
    if ($i % 2 === 0) {
        continue;
    }
    echo "$i ";
}
// 輸出:1 3 5 7 9
?>

跳過無效資料

<?php
$data = ['Alice', '', 'Bob', null, 'Charlie', '   '];

$validNames = [];

foreach ($data as $name) {
    // 跳過空值或只有空白的字串
    if (empty(trim($name ?? ''))) {
        continue;
    }
    $validNames[] = trim($name);
}

print_r($validNames);
// ['Alice', 'Bob', 'Charlie']
?>

在巢狀迴圈中使用 continue

使用 continue n 可以跳過外層迴圈的當前迭代:

<?php
for ($i = 1; $i <= 3; $i++) {
    for ($j = 1; $j <= 3; $j++) {
        if ($j === 2) {
            continue 2;  // 跳到外層迴圈的下一次迭代
        }
        echo "($i, $j) ";
    }
    echo "這行不會被執行到\n";
}
echo "\n";
?>

輸出:

(1, 1) (2, 1) (3, 1) 

break vs continue

<?php
echo "break 範例:";
for ($i = 1; $i <= 5; $i++) {
    if ($i === 3) {
        break;  // 完全跳出迴圈
    }
    echo "$i ";
}
echo "\n";
// 輸出:1 2

echo "continue 範例:";
for ($i = 1; $i <= 5; $i++) {
    if ($i === 3) {
        continue;  // 跳過這次迭代
    }
    echo "$i ";
}
echo "\n";
// 輸出:1 2 4 5
?>

while 迴圈中的注意事項

while 迴圈中使用 continue 時,要注意更新條件變數的位置:

<?php
// 錯誤示範 - 會造成無限迴圈
$i = 0;
while ($i < 5) {
    if ($i === 2) {
        continue;  // 跳過了 $i++,造成無限迴圈
    }
    echo "$i ";
    $i++;
}

// 正確寫法
$i = 0;
while ($i < 5) {
    $i++;  // 在 continue 之前更新
    if ($i === 3) {
        continue;
    }
    echo "$i ";
}
// 輸出:1 2 4 5
?>

實際應用範例

搜尋陣列

<?php
$users = [
    ['id' => 1, 'name' => 'Alice', 'active' => true],
    ['id' => 2, 'name' => 'Bob', 'active' => false],
    ['id' => 3, 'name' => 'Charlie', 'active' => true],
];

// 找到第一個非活躍用戶
$inactiveUser = null;

foreach ($users as $user) {
    if ($user['active']) {
        continue;  // 跳過活躍用戶
    }
    
    $inactiveUser = $user;
    break;  // 找到後跳出
}

if ($inactiveUser) {
    echo "找到非活躍用戶:" . $inactiveUser['name'];
}
?>

驗證輸入

<?php
$inputs = [
    'name' => 'Alice',
    'email' => 'invalid-email',
    'age' => 25,
    'website' => '',
];

$errors = [];

foreach ($inputs as $field => $value) {
    // 跳過空的可選欄位
    if ($field === 'website' && empty($value)) {
        continue;
    }
    
    // 驗證 email
    if ($field === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
        $errors[] = "Email 格式不正確";
        continue;
    }
    
    // 驗證必填欄位
    if (empty($value) && in_array($field, ['name', 'email'])) {
        $errors[] = ucfirst($field) . " 不能為空";
    }
}

if (!empty($errors)) {
    foreach ($errors as $error) {
        echo "錯誤:$error\n";
    }
}
?>

處理 CSV 資料

<?php
$csvData = "name,age,city
Alice,25,Taipei
Bob,invalid,Taichung
,30,Kaohsiung
Charlie,35,Tainan";

$lines = explode("\n", $csvData);
$header = null;
$records = [];

foreach ($lines as $index => $line) {
    // 跳過空行
    if (empty(trim($line))) {
        continue;
    }
    
    $fields = str_getcsv($line);
    
    // 第一行是標題
    if ($index === 0) {
        $header = $fields;
        continue;
    }
    
    // 驗證資料
    if (empty($fields[0])) {
        echo "第 $index 行:名稱為空,跳過\n";
        continue;
    }
    
    if (!is_numeric($fields[1])) {
        echo "第 $index 行:年齡不是數字,跳過\n";
        continue;
    }
    
    $records[] = array_combine($header, $fields);
}

print_r($records);
?>

遊戲迴圈

<?php
$maxRounds = 10;
$score = 0;

for ($round = 1; $round <= $maxRounds; $round++) {
    echo "第 $round 回合\n";
    
    // 模擬擲骰子
    $dice = random_int(1, 6);
    echo "擲出:$dice\n";
    
    // 擲到 1 扣分並跳過
    if ($dice === 1) {
        $score = max(0, $score - 5);
        echo "擲到 1,扣 5 分,目前分數:$score\n\n";
        continue;
    }
    
    // 擲到 6 獲得大獎並結束
    if ($dice === 6) {
        $score += 50;
        echo "擲到 6!獲得 50 分大獎!\n";
        echo "最終分數:$score\n";
        break;
    }
    
    $score += $dice;
    echo "獲得 $dice 分,目前分數:$score\n\n";
}

if ($round > $maxRounds) {
    echo "遊戲結束,最終分數:$score\n";
}
?>

檔案處理

<?php
$files = ['data.txt', 'config.json', 'temp.tmp', 'readme.md', 'backup.bak'];
$processedFiles = [];

foreach ($files as $file) {
    // 跳過暫存檔和備份檔
    $ext = pathinfo($file, PATHINFO_EXTENSION);
    
    if (in_array($ext, ['tmp', 'bak'])) {
        echo "跳過暫存/備份檔:$file\n";
        continue;
    }
    
    // 模擬檔案處理
    echo "處理檔案:$file\n";
    $processedFiles[] = $file;
    
    // 如果已處理 3 個檔案就停止
    if (count($processedFiles) >= 3) {
        echo "已達處理上限\n";
        break;
    }
}

echo "\n已處理的檔案:\n";
print_r($processedFiles);
?>