Die Match Expression, eingeführt in PHP 8.0, ist eine der
bedeutendsten Erweiterungen der Sprachsyntax und stellt eine moderne,
leistungsfähige Alternative zur traditionellen
switch-Anweisung dar. Dieses neue Sprachmerkmal verbessert
die Lesbarkeit, Kompaktheit und Sicherheit des Codes bei der
Durchführung von bedingten Vergleichen.
Die Match Expression führt einen Wert gegen eine Reihe von
Bedingungen und gibt das Ergebnis des ersten passenden Arms zurück. Im
Gegensatz zur switch-Anweisung ist Match:
===) anstelle von losen
Vergleichen (==)break-Anweisungen, um Fall-Through zu
verhindernHier ist ein einfacher Vergleich zwischen der traditionellen
switch-Anweisung und der neuen Match Expression:
// Herkömmlicher switch-Ansatz
function getStatusText($status) {
switch ($status) {
case 200:
return 'OK';
case 404:
return 'Not Found';
case 500:
return 'Internal Server Error';
default:
return 'Unknown Status';
}
}
// Entsprechender Match-Ansatz
function getStatusText($status) {
return match ($status) {
200 => 'OK',
404 => 'Not Found',
500 => 'Internal Server Error',
default => 'Unknown Status',
};
}Die Match Expression ist deutlich prägnanter und vermeidet typische
Fehler, die bei Verwendung von switch auftreten können, wie
vergessene break-Anweisungen.
Match verwendet standardmäßig strikte Typvergleiche
(===):
$result = match ($value) {
'1' => 'Zeichenkette 1',
1 => 'Zahl 1',
true => 'Boolean true',
default => 'Nichts hat gepasst'
};Hier wird nur der Arm ausgeführt, der exakt dem Typ und Wert von
$value entspricht.
Match erlaubt mehrere Bedingungen für jeden Arm, durch Kommas getrennt:
$httpStatus = 418;
$statusMessage = match ($httpStatus) {
200, 201, 202 => 'Erfolg',
400, 401, 403, 404 => 'Client-Fehler',
500, 502, 503 => 'Server-Fehler',
418 => "I'm a teapot",
default => 'Unbekannt'
};
echo $statusMessage; // Ausgabe: "I'm a teapot"Match kann Ausdrücke sowohl für den zu vergleichenden Wert als auch für die Ergebnisse verwenden:
$alter = 25;
$altersgruppe = match (true) {
$alter < 18 => 'Minderjährig',
$alter >= 18 && $alter < 65 => 'Erwachsen',
$alter >= 65 => 'Senior',
};
echo $altersgruppe; // Ausgabe: "Erwachsen"Dieses Muster mit match(true) ist besonders nützlich für
Bereichsvergleiche und komplexe Bedingungen.
Jeder Arm kann komplexe Ausdrücke oder Funktionsaufrufe enthalten:
$ergebnis = match ($wert) {
1 => berechneEtwas(),
2 => $this->doOperation($wert),
3, 4 => function() use ($wert) { return $wert * 2; }(),
default => throw new Exception("Ungültiger Wert: $wert"),
};Match erzwingt die Behandlung aller möglichen Fälle. Wenn keine
Übereinstimmung gefunden wird und kein default-Arm
vorhanden ist, wird eine UnhandledMatchError-Exception
ausgelöst:
$farbe = 'Lila';
try {
$rgb = match ($farbe) {
'Rot' => [255, 0, 0],
'Grün' => [0, 255, 0],
'Blau' => [0, 0, 255],
};
} catch (UnhandledMatchError $e) {
echo "Fehler: Unbekannte Farbe '$farbe'";
}Eine Stärke von Match ist die Möglichkeit, komplexe Bedingungsmuster zu erstellen:
$ergebnis = match (true) {
$wert instanceof DateTime => 'Es ist ein Datum',
is_array($wert) && count($wert) > 0 => 'Nicht-leeres Array',
is_string($wert) && str_starts_with($wert, 'http') => 'URL',
is_numeric($wert) && $wert > 0 => 'Positive Zahl',
default => 'Sonstiger Wert',
};Match eignet sich hervorragend für Validierungsszenarien:
function validateEmail($email) {
return match (true) {
$email === '' => 'E-Mail darf nicht leer sein',
!filter_var($email, FILTER_VALIDATE_EMAIL) => 'Ungültiges E-Mail-Format',
!checkDomainExists(extractDomain($email)) => 'Domain existiert nicht',
default => 'valid',
};
}
$validationResult = validateEmail('test@example.com');Match kann elegante Routenhandler ermöglichen:
$route = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];
$result = match (true) {
$route === '/users' && $method === 'GET' => getUsersList(),
$route === '/users' && $method === 'POST' => createUser($_POST),
$route === '/users/profile' && $method === 'GET' => getUserProfile($_GET['id']),
default => notFound(),
};Match kann für einfache Zustandsmaschinen verwendet werden:
class OrderStateMachine {
public function transition(Order $order, string $event) {
$currentState = $order->getState();
$newState = match ([$currentState, $event]) {
['new', 'confirm'] => 'confirmed',
['confirmed', 'ship'] => 'shipped',
['shipped', 'deliver'] => 'delivered',
['confirmed', 'cancel'],
['new', 'cancel'] => 'cancelled',
default => throw new InvalidTransitionException($currentState, $event),
};
$order->setState($newState);
return $order;
}
}Bei der Verwendung von Match Expressions sollten einige bewährte Praktiken beachtet werden:
Verwenden Sie Match für Rückgabewerte: Da Match ein Ausdruck ist, eignet es sich besonders gut für Szenarien, in denen ein Wert basierend auf einer Bedingung zurückgegeben werden soll.
Nutzen Sie die Typensicherheit: Der strikte Vergleich von Match führt zu sichererem Code. Nutzen Sie diesen Vorteil bewusst.
Vermeiden Sie übermäßige Komplexität: Obwohl Match sehr ausdrucksstark ist, sollten Sie zu komplexe Bedingungen in separate Funktionen auslagern, um die Lesbarkeit zu bewahren.
Bevorzugen Sie Match gegenüber switch: In den meisten Fällen ist Match die bessere Wahl als switch, da es kompakter, sicherer und ausdrucksstärker ist.
Denken Sie an Performance: Match ist in der Regel effizienter als verschachtelte if-else-Anweisungen, besonders bei vielen Bedingungen.
Match hat einige Einschränkungen, die beachtet werden sollten:
Keine Fall-Through-Mechanismen: Im Gegensatz zu
switch bietet Match keine Möglichkeit, Code für mehrere
Fälle gemeinsam auszuführen.
Kein Block-Syntax: Match akzeptiert nur einfache Ausdrücke auf der rechten Seite, keine Codeblöcke. Für komplexe Logik müssen Sie Funktionen verwenden.
Keine Dynamischen Keys: Die Bedingungen in Match müssen konstante Ausdrücke sein:
// Dies funktioniert NICHT:
$keys = [1, 2, 3];
$result = match ($value) {
$keys[0] => 'Fall 1', // Fehler
// ...
};