[PHP]breakとは?ループやswitchを途中で抜ける方法を徹底解説

PHP

はじめに

これまでの記事で、while・do-while・for・foreach という4つのループ構文、そして switch を解説してきましたが、その多くの実践例で既に登場していたのが、今回取り上げる break です。

break は、現在実行中のループ(while、do-while、for、foreach)や switch 文を、その場で即座に中断して抜けるための制御構文です。「特定の条件を満たしたら、それ以上繰り返す必要がない」という場面で、コードを無駄に実行し続けることを防ぎ、処理の意図を明確に表現できます。また、ネストしたループを複数階層まとめて抜ける際に使う、数値引数を使った応用的な書き方もあります。本記事では基本的な使い方から、continue との違い、実践的な活用例まで詳しく解説します。


構文概要

項目内容
構文名break
種別制御構造(言語構文)
基本構文break; または break n;(nは抜けるループの階層数)
対象while、do-while、for、foreach、switch
使用場所ループまたはswitchのブロック内でのみ有効
数値引数ネストしたループを複数階層まとめて抜ける際に指定する(デフォルトは1)
対応バージョンPHP 4以前から存在する最古参の構文の一つ

breakの動作(イメージ図)

  for ($i = 0; $i < 10; $i++) {
      if ($i === 3) {
          break;   ← ここでforループ全体を即座に抜ける
      }
      echo $i;
  }
  echo 'ループ終了後の処理';
              │
              ▼
  出力: 0, 1, 2, "ループ終了後の処理"
  ($i === 3 になった時点で、残りの繰り返し(3〜9)は
   一切実行されず、ループの次の行に処理が移る)

ポイントは、break がループ全体を即座に終了させるという点です。条件を満たした時点でそれ以降の繰り返しは一切行われず、制御はループの直後の行に移ります。


実践サンプル7選

例1:基本的な使い方

<?php

for ($i = 0; $i < 10; $i++) {
    if ($i === 5) {
        break;
    }
    echo "カウント: {$i}" . PHP_EOL;
}

echo 'ループを終了しました' . PHP_EOL;

例2:配列から目的の要素を見つけたら検索を打ち切る

<?php

$users = [
    ['id' => 1, 'name' => '太郎'],
    ['id' => 2, 'name' => '花子'],
    ['id' => 3, 'name' => '次郎'],
];

$foundUser = null;

foreach ($users as $user) {
    if ($user['id'] === 2) {
        $foundUser = $user;
        break; // 見つかったら、残りの要素をチェックする必要はない
    }
}

print_r($foundUser);

例3:switch内でのbreakの役割の再確認

<?php

function describeStatus(string $status): string
{
    switch ($status) {
        case 'active':
            $result = '稼働中';
            break; // breakがないと次のcaseにフォールスルーしてしまう
        case 'inactive':
            $result = '停止中';
            break;
        default:
            $result = '不明';
    }
    return $result;
}

echo describeStatus('active') . PHP_EOL;

例4:ネストしたループを複数階層まとめて抜ける

<?php

$matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
$target = 5;
$found = false;

foreach ($matrix as $rowIndex => $row) {
    foreach ($row as $colIndex => $value) {
        if ($value === $target) {
            echo "発見: 行{$rowIndex}, 列{$colIndex}" . PHP_EOL;
            $found = true;
            break 2; // 内側と外側、両方のループを同時に抜ける
        }
    }
}

if (!$found) {
    echo '見つかりませんでした' . PHP_EOL;
}

例5:無限ループ(while (true))からの脱出条件として

<?php

$attempts = 0;

/**
 * あえて条件なしの無限ループとして開始し、
 * 内部のbreakで終了条件を明示的に制御する設計パターン
 */
while (true) {
    $attempts++;
    echo "試行{$attempts}回目" . PHP_EOL;

    if ($attempts >= 3) {
        echo '最大試行回数に達しました' . PHP_EOL;
        break;
    }
}

例6:早期終了によるパフォーマンス最適化

<?php

function hasDuplicate(array $items): bool
{
    $seen = [];

    foreach ($items as $item) {
        if (isset($seen[$item])) {
            // 重複を見つけた時点で、残りの要素を確認する必要はない
            return true; // この文脈ではreturnがbreakと同様の早期終了の役割を果たす
        }
        $seen[$item] = true;
    }

    return false;
}

var_dump(hasDuplicate(['a', 'b', 'c', 'b'])); // true('b'が重複した時点で判定を打ち切る)

例7:switch内でのネストしたループに対するbreakの階層指定

<?php

foreach ([1, 2, 3] as $i) {
    switch ($i) {
        case 2:
            // switch内のbreak 1はswitch自体を抜けるだけで、
            // 外側のforeachは継続される
            echo "{$i}はケース2です" . PHP_EOL;
            break;
        default:
            echo "{$i}はデフォルトケースです" . PHP_EOL;

            if ($i === 3) {
                break 2; // switchとforeachの両方を同時に抜ける
            }
    }
}

echo '処理完了' . PHP_EOL;

関連機能との比較

機能役割breakとの違い
breakループやswitchを即座に抜ける本記事の対象。処理全体を終了させる
continue現在の繰り返しだけをスキップし、次の繰り返しに進むループ自体は終了せず、継続する点が大きく異なる
return関数・メソッドの実行を終了し、値を返すループだけでなく、関数全体を抜ける、より強い制御構文
exit / dieスクリプト全体の実行を終了するループや関数の範囲を超えて、プログラム全体を停止させる
goto指定したラベルへ処理をジャンプするより自由度が高いが、可読性を損ないやすいため限定的に使われる

よくある落とし穴(注意点)

  1. continueとの混同 break はループ「全体」を終了させますが、continue は現在の繰り返し「1回だけ」をスキップして次に進みます。この2つの役割を混同すると、意図と異なる挙動になります。
  2. 数値引数(break n;)の階層の数え方を誤る break 2; のように数値を指定する場合、その数値は「内側から数えて何階層抜けるか」を表します。ネストが深くなると、どの break がどの階層まで影響するのかが分かりにくくなるため、過度に深いネストでの多用は避け、必要であれば関数への切り出しを検討しましょう(例4・例7を参照)。
  3. switch内のbreakとループのbreakを混同する switch が foreach などのループ内にネストしている場合、switch 内で単に break; と書くと、それは switch 自体を抜けるだけであり、外側のループは継続します。外側のループまで一緒に抜けたい場合は、break 2; のように明示的に階層を指定する必要があります(例7を参照)。
  4. do-whileの条件式部分でのスコープに注意する do { ... break; } while (条件); のように break でループを抜けた場合、while の条件式はそもそも評価されません。ループ終了後の処理が、条件の真偽に依存しない設計になっているか確認しましょう。
  5. 関数内ではreturnの方が意図が明確な場合もある 関数の中でループを使っていて、特定の条件が見つかった時点で関数自体の処理を終えたい場合、break でループを抜けてから別途 return するよりも、直接 return する方がコードがシンプルになることがあります(例6を参照)。

まとめ

観点まとめ
何をする構文か現在実行中のループまたはswitchを即座に中断し、その範囲の外側へ処理を移す
主な用途条件に合致した要素が見つかった時点での検索打ち切り、無限ループからの脱出
数値引数break n;でネストしたループを複数階層まとめて抜けられる
continueとの違いbreakはループ全体を終了、continueは現在の繰り返しだけをスキップ
注意点switchとループが入れ子の場合の階層指定、深いネストでの可読性低下

break は、ループや switch の処理を無駄なく打ち切るための、シンプルかつ強力な制御構文です。continue との役割の違いを正しく理解し、ネストが深くなる場合は数値引数の階層指定に注意しながら、意図の伝わりやすいコードを書いていきましょう。

タイトルとURLをコピーしました