PHP 8.4.1 Released!

switch

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

Die switch-Anweisung entspricht in etwa einer Folge von if-Anweisungen die jeweils den gleichen Ausdruck prüfen. Es kommt oft vor, dass man dieselbe Variable (oder denselben Ausdruck) gegen viele verschiedene mögliche Werte prüfen und abhängig davon unterschiedlichen Code ausführen möchte. Genau hierfür wurde die switch-Anweisung eingeführt.

Hinweis: Beachten Sie, dass im Unterschied zu einigen anderen Sprachen die continue-Anweisung auch auf switch anwendbar ist und sich ähnlich wie break verhält. Wenn Sie ein switch innerhalb einer Schleife verwenden und mit dem nächsten Schleifendurchlauf beginnen wollen so müssen Sie in diesem Fall continue 2 angeben.

Hinweis:

Beachten Sie auch, dass switch/case typschwache Vergleiche durchführt.

Im folgenden Beispiel sind die beiden Codeblöcke gleichwertig. Der eine verwendet eine Reihe von if- und elseif-Anweisungen und der andere eine switch-Anweisung. Die Ausgabe ist in beiden Fällen dieselbe.

Beispiel #1 switch-Anweisung

<?php
// This switch statement:

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

// Is equivalent to:

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

Um Fehler zu vermeiden ist es wichtig zu verstehen wie eine switch-Anweisung ausgeführt wird. Eine switch-Anweisung wird zeilenweise (genauer: Anweisung für Anweisung) ausgewertet. Zunächst einmal wird überhaupt kein Code ausgeführt. Erst wenn eine case-Anweisung gefunden wird, deren Ausdruck zu einem Wert evaluiert, der dem an switch übergebenen Ausdruck entspricht, beginnt PHP tatsächlich die folgenden Anweisungen auszuführen. Die Ausführung wird fortgesetzt bis das Ende der switch-Anweisung erreicht ist oder bis PHP bei der Ausführung auf eine break-Anweisung stößt. Wenn Sie am Ende der Anweisungsliste eines case kein break setzen, so wird die Ausführung mit dem nächsten case fortgesetzt, z. B.:

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

Wenn in diesem Beispiel $i gleich 0 ist, führt PHP alle echo-Anweisungen aus! Ist $i gleich 1, führt PHP die letzten beiden echo-Anweisungen aus. Sie erreichen das erwartete Verhalten nur, wenn $i gleich 2 ist. Daher ist es wichtig break-Anweisungen nicht zu vergessen (auch wenn Sie gelegentlich absichtlich darauf verzichten werden, diese unter bestimmten Bedingungen anzugeben).

In einer switch-Anweisung wird die Bedingung nur einmal ausgewertet und das Ergebnis mit jeder case-Anweisung verglichen. In einer elseif-Anweisung wird die Bedingung erneut ausgewertet. Wenn Ihre Bedingung komplizierter ist als ein einfacher Vergleich, und/oder sich in einer dichten Schleife befindet, kann ein switch schneller sein.

Die Anweisungsliste eines case kann ebenso leer sein, was einfach die Kontrolle an die Anweisungsliste des nächsten case übergibt.

<?php
switch ($i) {
case
0:
case
1:
case
2:
echo
"i ist kleiner als 3, aber nicht negativ";
break;
case
3:
echo
"i ist 3";
}
?>

Ein Sonderfall ist die default-Klausel. Diese fängt alles ab, was nicht durch eine der anderen case-Klauseln behandelt wurde. Zum Beispiel:

<?php
switch ($i) {
case
0:
echo
"i ist gleich 0";
break;
case
1:
echo
"i ist gleich 1";
break;
case
2:
echo
"i ist gleich 2";
break;
default:
echo
"i ist nicht gleich 0, 1 oder 2";
}
?>

Hinweis: Mehrere default case-Anweisungen erzeugen einen E_COMPILE_ERROR-Fehler.

Hinweis: Technisch gesehen kann der default-Case an einer beliebigen Stelle stehen. Er wird nur verwendet, wenn kein anderer Fall passt. Nach gängiger Praxis ist es jedoch am besten, ihn als letzten Punkt ans Ende zu setzen.

Wenn kein case-Zweig passt und es keinen default-Zweig gibt, dann wird kein Code ausgeführt, genauso wie wenn keine if-Anweisung true wäre.

Ein case-Wert kann als Ausdruck angegeben werden. Dieser Ausdruck wird jedoch für sich allein ausgewertet und dann nur einfach mit dem switch-Wert verglichen. Das bedeutet, dass er nicht für komplexe Auswertungen des switch-Wertes verwendet werden kann. Zum Beispiel:

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

// Gibt "B" aus
?>

Für komplexere Vergleiche kann der Wert true als Switch-Wert verwendet werden. Statt switch können alternativ auch if-else-Blöcke verwendet werden.

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

// Gibt "B" aus
?>

Die alternative Syntax für Kontrollstrukturen wird von switch-Anweisungen unterstützt. Weitere Information entnehmen Sie dem Abschnitt Alternative Syntax für Kontrollstrukturen.

<?php
switch ($i):
case
0:
echo
"i ist gleich 0";
break;
case
1:
echo
"i ist gleich 1";
break;
case
2:
echo
"i ist gleich 2";
break;
default:
echo
"i ist nicht gleich 0, 1 oder 2";
endswitch;
?>

Es ist möglich, ein Semikolon anstelle eines Doppelpunkts nach einem case zu verwenden, wie:

<?php
switch($beer)
{
case
'Bitburger';
case
'Erdinger';
case
'Jever';
echo
'Gute Wahl';
break;
default;
echo
'Bitte treffen Sie eine andere Wahl...';
break;
}
?>

Siehe auch

add a note

User Contributed Notes 6 notes

up
289
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
82
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
6
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
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
4
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";
}

?>
To Top