switch

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

The switch statement is similar to a series of IF statements on the same expression. In many occasions, you may want to compare the same variable (or expression) with many different values, and execute a different piece of code depending on which value it equals to. This is exactly what the switch statement is for.

Note: Note that unlike some other languages, the continue statement applies to switch and acts similar to break. If you have a switch inside a loop and wish to continue to the next iteration of the outer loop, use continue 2.

Note:

Note that switch/case does loose comparison.

In the following example, each code block is equivalent. One uses a series of if and elseif statements, and the other a switch statement. In each case, the output is the same.

Example #1 switch structure

<?php
// This switch statement:

switch ($i) {
case
0:
echo
"i equals 0";
break;
case
1:
echo
"i equals 1";
break;
case
2:
echo
"i equals 2";
break;
}

// Is equivalent to:

if ($i == 0) {
echo
"i equals 0";
} elseif (
$i == 1) {
echo
"i equals 1";
} elseif (
$i == 2) {
echo
"i equals 2";
}
?>

It is important to understand how the switch statement is executed in order to avoid mistakes. The switch statement executes line by line (actually, statement by statement). In the beginning, no code is executed. Only when a case statement is found whose expression evaluates to a value that matches the value of the switch expression does PHP begin to execute the statements. PHP continues to execute the statements until the end of the switch block, or the first time it sees a break statement. If you don't write a break statement at the end of a case's statement list, PHP will go on executing the statements of the following case. For example:

<?php
switch ($i) {
case
0:
echo
"i equals 0";
case
1:
echo
"i equals 1";
case
2:
echo
"i equals 2";
}
?>

Here, if $i is equal to 0, PHP would execute all of the echo statements! If $i is equal to 1, PHP would execute the last two echo statements. You would get the expected behavior ('i equals 2' would be displayed) only if $i is equal to 2. Thus, it is important not to forget break statements (even though you may want to avoid supplying them on purpose under certain circumstances).

In a switch statement, the condition is evaluated only once and the result is compared to each case statement. In an elseif statement, the condition is evaluated again. If your condition is more complicated than a simple compare and/or is in a tight loop, a switch may be faster.

The statement list for a case can also be empty, which simply passes control into the statement list for the next case.

<?php
switch ($i) {
case
0:
case
1:
case
2:
echo
"i is less than 3 but not negative";
break;
case
3:
echo
"i is 3";
}
?>

A special case is the default case. This case matches anything that wasn't matched by the other cases. For example:

<?php
switch ($i) {
case
0:
echo
"i equals 0";
break;
case
1:
echo
"i equals 1";
break;
case
2:
echo
"i equals 2";
break;
default:
echo
"i is not equal to 0, 1 or 2";
}
?>

Note: Multiple default cases will raise a E_COMPILE_ERROR error.

Note: Technically the default case may be listed in any order. It will only be used if no other case matches. However, by convention it is best to place it at the end as the last branch.

If no case branch matches, and there is no default branch, then no code will be executed, just as if no if statement was true.

A case value may be given as an expression. However, that expression will be evaluated on its own and then loosely compared with the switch value. That means it cannot be used for complex evaluations of the switch value. For example:

<?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;
}

// Prints "B"
?>

For more complex comparisons, the value true may be used as the switch value. Or, alternatively, if-else blocks instead of switch.

<?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;
}

// Prints "B"
?>

The alternative syntax for control structures is supported with switches. For more information, see Alternative syntax for control structures.

<?php
switch ($i):
case
0:
echo
"i equals 0";
break;
case
1:
echo
"i equals 1";
break;
case
2:
echo
"i equals 2";
break;
default:
echo
"i is not equal to 0, 1 or 2";
endswitch;
?>

It's possible to use a semicolon instead of a colon after a case like:

<?php
switch($beer)
{
case
'tuborg';
case
'carlsberg';
case
'stella';
case
'heineken';
echo
'Good choice';
break;
default;
echo
'Please make a new selection...';
break;
}
?>

See Also

add a note

User Contributed Notes 7 notes

up
288
MaxTheDragon at home dot nl
12 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
121
septerrianin at mail dot ru
6 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
83
nospam at please dot com
24 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:
}
up
1
php at nospam dot k39 dot se
3 months ago
It is possible to prevent nested switch/match/if blocks by checking for multiple cases at once (just beware that PHP uses loose comparison here).

<?php
$a
= "abc";
$b = "def";

switch ([
$a, $b]) {
case [
"abc", "def"]:
$result = 1;
break;
default:
$result = -1;
}
// $result == 1
?>

If for some cases one of the values is not important, you can use the variable itself:

<?php
$a
= "abc";
$b = "def";

switch ([
$a, $b]) {
case [
"xyz", "def"]:
$result = 1;
break;
case [
$a, "def"]:
$result = 2;
break;
default:
$result = -1;
}
// $result == 2
?>
up
5
me at czarpino dot com
2 years ago
Although noted elsewhere, still worth noting is how loose comparison in switch-case was also affected by the change in string to number comparison. Prior PHP8, strings were converted to int before comparison. The reverse is now true which can cause issues for logic that relied on this behavior.

<?php
function testSwitch($key) {
switch (
$key) {
case
'non numeric string':
echo
$key . ' matches "non numeric string"';
break;
}
}

testSwitch(0); // pre-PHP8, returns '0 matches "non numeric string"'
?>
up
3
j dot kane dot third at gmail dot com
1 year ago
The default case appears to always be evaluated last. If break is excluded from the default case, then the proceeding cases will be reevaluated. This behavior appears to be undocumented.

<?php

$kinds
= ['moo', 'kind1', 'kind2'];

foreach (
$kinds as $kind) {
switch(
$kind)
{
default:
// The kind wasn't valid, set it to the default
$kind = 'kind1';
var_dump('default');

case
'kind1':
var_dump('1');
break;

case
'kind2':
var_dump('2');
break;

case
'kindn':
var_dump('n-th');
break;
}

echo
"\n\n";
}

?>
up
-4
GeorgNation
1 year ago
You can wrap up the case/break block with a curly braces:

$x = 2;

switch ($x)
{
case 2: {
echo '2 entrypoint';
break;
}

default: {
echo 'default entrypoint';
break;
}
}
To Top