In unserer letzten Folge haben wir die kommenden Verbesserungen am PHP-Typsystem besprochen. Heute sehen wir uns ein neues Konstrukt an, das die Verzweigungslogik noch leistungsfähiger macht.
PHP hat seit Anbeginn der Zeit eine switch-Anweisung
, die dem gleichen Konstrukt in C nachempfunden ist. Sie haben es sicher schon einmal gesehen:
<?php switch ($var) { case 'a': $message = "Die Variable war a."; break; case 'b': $message = "Die Variable war c."; break; case 'c': $message = "Die Variable war c."; break; default: $message = "Die Variable war etwas anderes."; break; } print $message;
Der klassische Schalter erfüllt zwar seine Aufgabe, hat aber eine Reihe von Einschränkungen. Die meisten neueren Sprachen wie Go oder Rust haben sich für robustere, weniger fehleranfällige Strukturen entschieden, die auf eine Vielzahl von Namen zurückgreifen. Und jetzt hat auch PHP eine.
Hier kommt die PHP-Funktion match
ins Spiel. Anders als switch
ist PHP match
ein Ausdruck. Das bedeutet, dass er zu einem Wert ausgewertet wird, etwa so:
<?php $message = match($var) { 'a' => 'Die Variable war a', 'b' => 'Die Variable war b', 'c' => 'Die Variable war c', default => 'Die Variable war etwas anderes', }; print $message;
Hier gibt es mehrere Dinge zu beachten:
switch
wird jeder Fall
mit loser Gleichheit ==
verglichen. Bei PHP match
wird jeder Zweig mit strikter Gleichheit ===
verglichen. Das bedeutet, dass auch die Typen übereinstimmen müssen.match
ist nur ein einziger Ausdruck. Keine mehrzeiligen Anweisungen, nur ein einziger Ausdruck, der ausgewertet wird. Wenn Sie eine komplexe Logik benötigen, machen Sie daraus eine Funktion oder Methode, die Sie aufrufen.Unterbrechung
erforderlich ist.match
gibt einen Wert zurück. Das ist der ganze Grund für seine Existenz.;
ganz am Ende erforderlich, genau wie bei Closure-Definitionen.match
ist erschöpfend. Wenn $var
nicht ===
einer der angegebenen Werte ist und es keinen Standardwert
gibt, wird ein Fehler ausgelöst.match-Zweige
können auch zusammengesetzt und durch Kommata getrennt werden, um ein "OR"-ähnliches Verhalten zu erreichen, etwa so:
<?php echo match($operator) { '+', '-', '*', '/' => 'Einfache Arithmetik', '%' => 'Modulus', '!' => 'Negation', };
PHP match
wurde als modernisierter, nützlicherer Schalter
angepriesen, aber ich bin mir nicht sicher, ob das so richtig ist. Ich betrachte match
eher als eine leistungsfähigere ternäre Funktion.
In der Vergangenheit habe ich mich oft in binären Fällen wiedergefunden, in denen eine Variable in Abhängigkeit von einer Bedingung einem von zwei Werten zugewiesen werden kann. Der einfachste Weg, dies zu schreiben, ist folgender:
<?php $display = $user->isAdmin() ? $user->name() . ' (admin)' : $user->name() . ' (muggle)' ;
Das ist ein absolut gültiger Code und ziemlich nützlich. Wenn die Logik in der Bedingung oder in einer der Verzweigungen zu komplex ist, um leicht lesbar zu sein, ist das ein Hinweis darauf, dass die Logik in eine eigene Funktion oder Methode umstrukturiert werden sollte. Ich habe festgestellt, dass dies eine wirklich gute Heuristik für Situationen wie diese ist und außerdem zu sehr lesbarem, kompaktem und testbarem Code führt.
Das funktioniert allerdings nur für true/false
. match
hingegen funktioniert für eine beliebige Anzahl von Optionen, hat aber denselben Anreiz, Sie zu gut fundiertem, sauberem Code zu bewegen.
Wenn Sie komplexere Bedingungen als die einfache Identität benötigen, können Sie match
on true
verwenden:
<?php $count = get_count(); $size = match(true) { $count > 0 && $count <=10 => 'small', $count <=50 => 'medium', $count >50 => 'huge', };
Da es keinen Standardwert
gibt, führt eine Nichtübereinstimmung (in diesem Fall, wenn $count
0 oder negativ ist) zu einem Fehler, anstatt dass eine Zuweisung zu null erfolgt und weitergemacht wird. Das ist gut, denn so können sich Fehler nicht ausbreiten und späteren Code verunreinigen.
Der Match Expression RFC wurde uns freundlicherweise von Ilija Tovilo zur Verfügung gestellt.