switch

(PHP 4, PHP 5, PHP 7, PHP 8)

switch文は、同じ式を用いてIF文を並べたのに似ています。 同じ変数を異なる値と比較し、値に応じて異なったコードを実行したいと 思うことがしばしばあるかと思います。 switch文は、まさにこのためにあるのです。

注意: 他の言語とは違って、 continue命令は switch にも適用され、breakと同じ動作をします。 ループの内部で switch を使用しており、 外側のループの処理を続行させたい場合には、continue 2 を使用してください。

注意:

switch/case が行うのは、 緩やかな比較 であることに注意しましょう。

次の二つの例は、同じことを二つの異なった方法で書いたものです。 一つは、ifelseif文を、 もう一つはswitch文を使っています。 どちらも、出力は同じです。

例1 switch 文の構造

<?php
// これが swtich 文です:

switch ($i) {
    case 
0:
        echo 
"iは0に等しい";
        break;
    case 
1:
        echo 
"iは1に等しい";
        break;
    case 
2:
        echo 
"iは2に等しい";
        break;
}

// 上記は、下記と同じです:
if ($i == 0) {
    echo 
"iは0に等しい";
} elseif (
$i == 1) {
    echo 
"iは1に等しい";
} elseif (
$i == 2) {
    echo 
"iは2に等しい";
}

?>

失敗を避けるためにswitch文がどのように実行されるのかを 理解することが重要です。 switch文は、行毎に実行されます。 (実際には、文毎に実行されます。)初めは、何も実行しません。 switch式の値と同じ値として評価される式を有する case文が見つけられたときに初めてPHPにより 命令の実行が行われます。 PHPはswitchブロックの終わりまたは最初の break文まで実行を続けます。 CASE文の終わりにbreak文を書かない場合は、PHPは 次のCASE文を実行しつづけます。例えば、

<?php
switch ($i) {
    case 
0:
        echo 
"iは0に等しい";
    case 
1:
        echo 
"iは1に等しい";
    case 
2:
        echo 
"iは2に等しい";
}
?>

ここで、$iが0に等しい場合は、PHPは全ての echo 文を出力してしまいます! $iが1の場合、PHPは最後の二つの echo 文を出力します。 $iが2に等しい場合のみ、'期待した'動作をし、 'iは2に等しい'と表示します。 このため (ある種の状況下では、BREAKを付加することを避けたいと 思うかもしれませんが)、 break文を忘れないようにすることが重要です。

switch文では、条件は1度だけ評価され、 その結果が各case文と比較されます。 elseif文では、条件は、再度評価されます。 使用する条件が単純な比較処理よりも複雑な処理を行ったり、 重い繰り返し処理を行う場合、switchの方が より処理が速い可能性があります。

caseに付随する文は、空とすることが可能です。 この場合、次のcaseに付随する文に制御が移行します。

<?php
switch ($i) {
    case 
0:
    case 
1:
    case 
2:
        echo 
"iは3より小さいですが負ではありません";
        break;
    case 
3:
        echo 
"iは3です";
}
?>

default は、case 文の特別な場合です。これは他の全ての case にマッチしない場合に実行されます。例を以下に示します。

<?php
switch ($i) {
    case 
0:
        echo 
"iは0に等しい";
        break;
    case 
1:
        echo 
"iは1に等しい";
        break;
    case 
2:
        echo 
"iは2に等しい";
        break;
    default:
       echo 
"iは0,1,2に等しくない";
}
?>

注意: 複数の default を置くと、 E_COMPILE_ERROR エラーが発生します。

注意: 技術的には、 default は switch 文の中のどの位置でも置くことができます。 default は他の case にマッチしなかった場合に使われるものです。 しかし、規約上は最後に置くのが一番です。

どの case にもマッチせず、 default も存在しない場合、 どのコードも実行されません。これは、 どの if 文も true でなかった場合と同じです。

case に与える値は、式であっても構いません。 しかし、式はそれ自体が実行され、 その結果が swtich に与えた値と緩やかに比較されます。 これは、switch に与える値の複雑な評価には使えないということです。 たとえば、以下の例を見てみましょう:

<?php
$target 
1;
$start 3;
switch (
$target) {
    case 
$start 1:
        print 
"A";
        break;
    case 
$start 2:
        print 
"B";
        break;
    case 
$start 3:
        print 
"C";
        break;
    case 
$start 4:
        print 
"D";
        break;
}
// "B" を出力します。
?>

もっと複雑な比較を行うには、 true をswitch文の値として指定するやり方が使えます。 もしくは、switch文ではなく、 if-elseブロックが使えます。

<?php
$offset 
1;
$start 3;
switch (
true) {
    case 
$start $offset === 1:
        print 
"A";
        break;
    case 
$start $offset === 2:
        print 
"B";
        break;
    case 
$start $offset === 3:
        print 
"C";
        break;
    case 
$start $offset === 4:
        print 
"D";
        break;
}
// "B" を出力します。
?>

switch文の制御構造に関する別の構文がサポートされています。 詳細は、 制御構造に関する別の構文を参照ください。

<?php
switch ($i):
    case 
0:
        echo 
"iは0に等しい";
        break;
    case 
1:
        echo 
"iは1に等しい";
        break;
    case 
2:
        echo 
"iは2に等しい";
        break;
    default:
        echo 
"iは0でも1でも2でもない";
endswitch;
?>

case の最後はコロンではなくセミコロンとすることもできます。たとえば次のようになります。

<?php
switch($beer)
{
    case 
'ツボルグ';
    case 
'カールスバーグ';
    case 
'ステラ';
    case 
'ハイネケン';
        echo 
'いいっすねぇ';
        break;
    default;
        echo 
'ほかのを選んでみませんか?';
        break;
}
?>

参考

add a note

User Contributed Notes 3 notes

up
269
MaxTheDragon at home dot nl
10 years ago
This is listed in the documentation above, but it's a bit tucked away between the paragraphs. The difference between a series of if statements and the switch statement is that the expression you're comparing with, is evaluated only once in a switch statement. I think this fact needs a little bit more attention, so here's an example:

<?php
$a
= 0;

if(++
$a == 3) echo 3;
elseif(++
$a == 2) echo 2;
elseif(++
$a == 1) echo 1;
else echo
"No match!";

// Outputs: 2

$a = 0;

switch(++
$a) {
    case
3: echo 3; break;
    case
2: echo 2; break;
    case
1: echo 1; break;
    default: echo
"No match!"; break;
}

// Outputs: 1
?>

It is therefore perfectly safe to do:

<?php
switch(winNobelPrizeStartingFromBirth()) {
case
"peace": echo "You won the Nobel Peace Prize!"; break;
case
"physics": echo "You won the Nobel Prize in Physics!"; break;
case
"chemistry": echo "You won the Nobel Prize in Chemistry!"; break;
case
"medicine": echo "You won the Nobel Prize in Medicine!"; break;
case
"literature": echo "You won the Nobel Prize in Literature!"; break;
default: echo
"You bought a rusty iron medal from a shady guy who insists it's a Nobel Prize..."; break;
}
?>

without having to worry about the function being re-evaluated for every case. There's no need to preemptively save the result in a variable either.
up
92
septerrianin at mail dot ru
4 years ago
php 7.2.8.
The answer to the eternal question " what is faster?":
1 000 000 000 iterations.

<?php
$s
= time();
for (
$i = 0; $i < 1000000000; ++$i) {
 
$x = $i%10;
  if (
$x == 1) {
   
$y = $x * 1;
  } elseif (
$x == 2) {
   
$y = $x * 2;
  } elseif (
$x == 3) {
   
$y = $x * 3;
  } elseif (
$x == 4) {
   
$y = $x * 4;
  } elseif (
$x == 5) {
   
$y = $x * 5;
  } elseif (
$x == 6) {
   
$y = $x * 6;
  } elseif (
$x == 7) {
   
$y = $x * 7;
  } elseif (
$x == 8) {
   
$y = $x * 8;
  } elseif (
$x == 9) {
   
$y = $x * 9;
  } else {
   
$y = $x * 10;
  }
}
print(
"if: ".(time() - $s)."sec\n");

$s = time();
for (
$i = 0; $i < 1000000000; ++$i) {
 
$x = $i%10;
  switch (
$x) {
  case
1:
   
$y = $x * 1;
    break;
  case
2:
   
$y = $x * 2;
    break;
  case
3:
   
$y = $x * 3;
    break;
  case
4:
   
$y = $x * 4;
    break;
  case
5:
   
$y = $x * 5;
    break;
  case
6:
   
$y = $x * 6;
    break;
  case
7:
   
$y = $x * 7;
    break;
  case
8:
   
$y = $x * 8;
    break;
  case
9:
   
$y = $x * 9;
    break;
  default:
   
$y = $x * 10;
  }
}
print(
"switch: ".(time() - $s)."sec\n");
?>

Results:
if: 69sec
switch: 42sec
up
99
nospam at please dot com
21 years ago
Just a trick I have picked up:

If you need to evaluate several variables to find the first one with an actual value, TRUE for instance. You can do it this was.

There is probably a better way but it has worked out well for me.

switch (true) {

  case (X != 1):

  case (Y != 1):

  default:
}
To Top