Match w PHP 8 – lepsza alternatywa switch

napis match vs switch

Każda nowa wersja PHP wywołuje spore emocje w społeczności. Chociaż ta najnowsza nie niesie ze sobą aż tylu wielkich zmian co wersja 7, to oczywiście jest kilka wartych uwagi nowości w PHP 8. Tym razem przyjrzę się bliżej nowemu wyrażeniu, które wydaje się bardzo sensowną alternatywą dla switch.

Obstawiam, że nie jeden programista już nie raz stworzył podobną metodę na własne potrzeby. Od tej wersji nie będzie to już potrzebne, gdyż do dyspozycji trafia match. Wydaje się, że ma kilka usprawnień w stosunku do konstrukcji switch i zdecydowanie jest warta uwagi. Już na samym początku chcę zaznaczyć, że słówko match staje się więc zarezerwowane. Trzeba będzie się go pozbyć z własnych metod czy funkcji.

Match – przykładowa implementacja

Poniżej prezentuję dwa bloki kodu, które działają prawie że tak samo. Prawie, bo jest kilka różnic. Myślę, że najłatwiej będzie pokazać plusy i minusy właśnie na przykładzie porównania. Na pierwszy rzut leci stary i dobrze znany switch, ale wcześniej jeszcze klasa z kilkoma stałymi, które zagwarantują nieco lepszą czytelność.

class Role
{
    public const ACCOUNTANT = 1;
    public const DIRECTOR = 2;
    public const ADMIN = 3;
    public const SUPER_ADMIN = 4;
}
switch ($role) {
    case Role::SUPER_ADMIN:
    case Role::ADMIN:
        $url = '/admin-panel';
        break;
    case Role::DIRECTOR:
        $url = '/director-panel';
        break;
    case Role::ACCOUNTANT:
        $url = '/billing-panel';
        break;
    default:
        $url = '/guest-panel';
}

Ten kawałek kodu na podstawie przekazanej wartości w postacie integera, która określa rolę w systemie, decyduje na jaki adres url przekierować logującego się do aplikacji użytkownika. Poniżej znajduje się ta sama funkcjonalność, ale wykorzystująca nowe wyrażenie.

$url = match ($role) {
    Role::SUPER_ADMIN, Role::ADMIN => '/admin-panel',
    Role::DIRECTOR => '/director-panel',
    Role::ACCOUNTANT => '/billing-panel',
    default => '/guest-panel'
};

Sam zapis wydaje się krótszy i chyba czytelniejszy. Jednak jak wspomniałem, istnieje kilka bardziej znaczących różnic.

Domyślna wartość

W obu przypadkach można zadeklarować domyślną wartość. Jeśli wyrażenie nie znajdzie dopasowania to wykona właśnie kawałek kodu określony jako default.

Brak dopasowania

Inaczej za to zachowają się obie konstrukcje w przypadku braku dopasowania. W obu kod wykonuje się z góry do dołu. Jeśli nie zostanie zadeklarowana domyślna wartość to w przypadku switch nie stanie się nic, za to match rzuci wyjątkiem UnhandledMatchError.

Restrykcyjność

Bardzo ważna rzecz. Gdyby odnieść to do porównania to switch użyje ==, za to match ===. Co w moim przykładzie przełoży się na to, że jeśli zmienna $role przyjęła wartość '2' to w pierwszej wersji do zmiennej $url trafi /director-panel, a w drugiej /guest-panel (wykona się wartość domyślna, bo nie znaleziono dopasowania).

Pojedyncze dopasowanie

O przerwanie konstrukcji switch w konkretnym miejscu trzeba zadbać samemu. Stąd też właśnie break; w każdym z bloków. Jeśli go nie ma, może się to skończyć kilkukrotnym dopasowaniem. Oczywiście w specyficznych przypadkach, bo zazwyczaj i tak nie uda się dopasować do więcej niż jednego.

Match i w tym wypadku jest precyzyjniejsze. Po prostu sama przerwie w momencie znalezienia pierwszego trafienia.

Zwracanie wartości

Match jest w stanie zwrócić wartość, za to switch nie. Nowy mechanizm staje się więc bardziej użyteczny w miejscach, gdzie rezultat ma być zachowany. Tak jest chociażby w przykładzie, który ja przygotowałem.

Dłuższe bloki kodu

Chyba największym minusem nowej funkcjonalności jest możliwość tylko i wyłącznie wywołania kodu jednolinijkowego. Za to w switchu przecież można tworzyć bloki kodu o dowolnej długości. Widać więc pewne ograniczenie.

Podsumowanie – switch czy match w PHP

Zapewne dla obu tych mechanizmów znajdą się konkretne zastosowania. Wyrażenie match może być szeroko wykorzystywane, bo jest bardzo przystępną opcją. Mimo wszystko switch nie zostanie całkowicie zastąpiony. Sprawdzi się przecież w miejscach, gdzie trzeba wykonać kilka operacji w ramach jednego dopasowania.

Jeśli chodzi o mnie, ja i tak rzadko używam switcha. Częściej sięgam po dobrze skonstruowane ify. Za to match jak najbardziej jest dla mnie czytelnym i wartościowym zabiegiem, więc myślę że trafi do mojej skrzynki narzędziowej już w pierwszych projektach implementowanych w PHP 8.

To jakie zastosowania znajdą się dla nowego mechanizmu okaże się dopiero w przyszłości. Tak jak jednak wspomniałem – bardzo przydatna funkcjonalność. W gąszczu niewielkich zmian w PHP 8 na pewno jedna z nielicznych, która bezapelacyjnie można określić jako zmianę na plus.

Krystian Żądło
Programista PHP i właściciel marki Koddlo. Pasjonat czystego kodu i dobrych praktyk programowania obiektowego. Prywatnie fan angielskiej piłki nożnej, dobrego humoru oraz podcastów.