switch i match — wiele opcji bez chaosu
🎯 Po tej lekcji wybierzesz jedną z wielu opcji czytelnie, używając switch lub match.
Kiedy Kuba pisze program sprawdzający dzień tygodnia, może użyć długiego łańcucha elseif. Ale gdy opcji jest wiele, kod robi się nieczytelny. Z pomocą przychodzą switch i nowoczesny match.
switch — klasyczne rozgałęzienie
switch porównuje jedną zmienną z wieloma możliwymi wartościami:
<?php
declare(strict_types=1);
$dzien = 'poniedziałek';
switch ($dzien) {
case 'sobota':
case 'niedziela':
echo 'Weekend — odpoczywaj!';
break;
case 'poniedziałek':
echo 'Początek tygodnia.';
break;
default:
echo 'Dzień roboczy.';
break;
}
// wynik: Początek tygodnia.
Kilka ważnych zasad switch:
- Porównanie jest luźne (
==), więcswitch(0)dopasujecase false. - Po każdym
casemusisz napisaćbreak, inaczej PHP "wpadnie" do kolejnegocase(tzw. fall-through). defaultwykona się, gdy żadencasenie pasuje.
break, PHP wykona też następny case — nawet jeśli jego warunek nie pasuje. To częste źródło błędów.match — nowoczesna alternatywa (PHP 8.0+)
match rozwiązuje problemy switch w elegancki sposób:
<?php
declare(strict_types=1);
$dzien = 3;
$nazwa = match($dzien) {
1 => 'poniedziałek',
2 => 'wtorek',
3 => 'środa',
4 => 'czwartek',
5 => 'piątek',
6 => 'sobota',
7 => 'niedziela',
};
echo 'Dzień tygodnia: ' . $nazwa;
// wynik: Dzień tygodnia: środa
1. Ścisłe porównanie
=== — typ musi się zgadzać (np. 1 nie pasuje do '1').2. Zwraca wartość —
match to wyrażenie, które możesz przypisać do zmiennej.3. Brak
break — każde ramię automatycznie kończy działanie; nie ma fall-through.UnhandledMatchError — match jest rygorystyczny
Gdy żadne ramię nie pasuje i nie ma default, PHP rzuca wyjątek \UnhandledMatchError:
<?php
declare(strict_types=1);
$status = 99;
// To rzuci wyjątek \UnhandledMatchError!
$opis = match($status) {
1 => 'aktywny',
0 => 'nieaktywny',
// brak default — błąd jeśli $status nie jest 0 ani 1
};
Dlatego zawsze dodawaj default albo miej pewność, że wszystkie możliwe wartości są obsłużone:
<?php
declare(strict_types=1);
$status = 99;
$opis = match($status) {
1 => 'aktywny',
0 => 'nieaktywny',
default => 'nieznany status',
};
echo $opis;
// wynik: nieznany status
Wiele wartości w jednym ramieniu
match pozwala podać kilka wartości w jednym ramieniu, oddzielonych przecinkiem:
<?php
declare(strict_types=1);
$dzien = 6;
$typ = match($dzien) {
1, 2, 3, 4, 5 => 'dzień roboczy',
6, 7 => 'weekend',
default => throw new \InvalidArgumentException('Nieznany dzień'),
};
echo $typ;
// wynik: weekend
Zauważ, że w default możesz rzucić wyjątek — throw w PHP 8 jest wyrażeniem.
Kiedy używać switch, a kiedy match?
| | switch | match |
|---|----------|---------|
| Porównanie | luźne == | ścisłe === |
| Zwraca wartość | nie | tak |
| Wymaga break | tak | nie |
| Fall-through | możliwy | niemożliwy |
| Brak dopasowania | nic się nie dzieje | \UnhandledMatchError |
| Styl | PHP < 8 | PHP 8+ ✓ |
W nowych projektach z PHP 8 używaj match — jest bezpieczniejszy i czytelniejszy.
Sprawdź się
Jaki operator porównania stosuje match?
match używa ścisłego porównania ===, więc typ musi się zgadzać. Różni go to od switch, który stosuje ==.
Co się stanie, jeśli żadne ramię match nie pasuje i nie ma ramienia default?
Gdy żadne ramię match nie pasuje i nie zdefiniowano default, PHP rzuca wyjątek \UnhandledMatchError. To ważna różnica względem switch, który po prostu nic nie robi.
Czy w match trzeba używać break?
match nie ma mechanizmu fall-through. Każde ramię zwraca wartość i wykonanie kończy się — break nie jest potrzebny ani dozwolony.
Ćwiczenie
Napisz skrypt z zmienną $dzien (liczba 1–7, gdzie 1 = poniedziałek). Używając match, przypisz do zmiennej $typ wartość 'dzień roboczy' dla dni 1–5 lub 'weekend' dla dni 6–7. Wyświetl wynik.
Pokaż rozwiązanie
<?php
declare(strict_types=1);
$dzien = 6;
$typ = match(true) {
$dzien >= 1 && $dzien <= 5 => 'dzień roboczy',
$dzien === 6 || $dzien === 7 => 'weekend',
default => throw new \InvalidArgumentException('Nieznany dzień'),
};
echo 'Dzień ' . $dzien . ' to: ' . $typ;
// wynik: Dzień 6 to: weekend