Menu

PHPのswitch文:case、break、フォールスルーの書き方

switch ($value)は1つの値をcaseラベルの一覧と比較し、最初に一致したところからbreakまでのコードを実行します。複数のcase、フォールスルー、default、switch(true)、そしてswitchがゆるい==比較を使う理由を扱います。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

switch ($value)は1つの値をcaseラベルの一覧と比較し、最初に一致したラベルの下にあるコードを実行します。各caseはbreakで終わり、どれにも一致しなかったものはすべてdefaultが処理します。

$dayを'fri'、'sun'、'wed'にして、もう一度実行してみてください。defaultが最後のcaseならbreakは不要です。

1つのブロックに複数のcase

複数の値で同じコードを実行するには、間に何も書かずにcaseラベルを並べます。一致したラベルは、その下のコードへと続きます。

matchと違い、switchにはcase 'jpg', 'jpeg':というカンマの構文はありません。ラベルを並べる方法しかありません。

フォールスルー:breakがないとどうなるか

switchを止めるのはbreakです。breakがないと、PHPは一致したcaseを実行したあと、ラベルを無視してその下のすべてのcaseへと進み、breakか終わりにたどり着くまで止まりません。

ここでのフォールスルーは意図的なもので、各プランは自分の機能に加えて、それより安いプランの機能をすべて受け取ります。意図して書くときは、次に読む人が「直して」しまわないよう、// no breakのようなコメントを付けましょう。意図していない場合、breakの書き忘れはswitchでもっともよくあるバグの1つです。

switchはゆるい比較(==)を使う

各caseは===ではなく==で確認されます。数値の文字列は数値に一致し、nullはfalseと""に一致し、trueはtrueと評価されるあらゆる値に一致します。セルをタップして2つの演算子を比べてみてください。

switchは==で、matchは===で比較する
Point at or tap a cell to read it as PHP.
$a == $b01"0""1"""nullfalsetrue"a""10""1e1"
0
1
"0"
"1"
""
null
false
true
"a"
"10"
"1e1"
Every cell computed by PHP 8.3.19.

実際の影響として、フォームから来た文字列"1"は何も変換しなくてもcase 1:に入ります。これはたいてい望ましい動きです。ただし、空でない文字列でのswitch (true)や、nullとcase false:の組み合わせは、予想外のcaseを選ぶことがあります。

nullの行に注目してください。null == 0がすでにtrueで、case 0:が先にあるので、case false:には届きません。ゆるい比較では、caseの順番で結果が変わります。PHP 8以降は0 == "a"がfalseなので(PHP 7ではtrueでした)、数値でない文字列がcase 0:に一致することはなくなりました。===が必要なら、このページの最後で扱うmatch式を使いましょう。

範囲や条件にはswitch(true)

caseラベルにはどんな式でも書けます。switch (true)にすると各caseが条件になり、最初にtrueと等しくなったものが選ばれます。

各caseが本当のboolになるようにしてください。ゆるい比較のため、case $name:は$nameが空でない文字列なら常に一致してしまいます。

ループの中のswitch:breakとcontinue

ループの中では、switch内のbreakはswitchから抜けるだけで、ループからは抜けません。ループを止めるにはbreak 2を使います。switch内のcontinueはbreakと同じ動きをし、PHPはコンパイル時に警告を出します:"continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?。ループの次の繰り返しに進むにはcontinue 2と書きます。

switchとmatchの違い

PHP 8で追加されたmatchは、switchのほとんどの用途をより少ないコードでこなします。===で比較し、値を返し、フォールスルーせず、カンマ区切りの条件を書け、何にも一致しないとUnhandledMatchErrorを投げるので、caseの書き忘れが黙って通り抜けることはありません。

caseに複数の文が必要なときや、プランの例のようにフォールスルーそのものが目的のときはswitchを使いましょう。値を結果に対応させるなら、matchのほうが短く安全です。

よくある質問

PHPのswitchで1つのブロックに複数のcaseを使うには?

間にコードを入れずにcaseラベルを並べます:case 'sat': case 'sun': echo 'weekend'; break;。各ラベルは共通のコードへフォールスルーします。switchにはcase 'sat', 'sun':という構文はなく、このカンマの形はmatchのものです。

PHPのswitchは厳密な比較を使いますか?

使いません。switchはゆるい==で比較するので、case '1':は整数の1に一致し、case 0:は'0'に一致します。厳密な===比較には、match式か、各caseの中で===を使うswitch (true)を使います。

PHPのswitchでbreakを忘れるとどうなりますか?

実行がフォールスルーします。一致したcaseのあと、PHPはbreakかreturnかswitchの終わりにたどり着くまで、その下にあるすべてのcaseのコードを実行し続けます。意図した動きのこともありますが、たいていはバグです。

PHPのswitchで「より大きい」のような範囲を判定できますか?

switch (true)を使えばできます。各caseにcase $score >= 90:のような条件を書き、最初にtrueになったものが実行されます。match (true)式も同じことを厳密な比較で行い、値を返します。

Coddyのプログラミング言語のイラスト

Coddyでコードを学ぼう

始める