Enum w PHP (PHP 8.1+) definiuje typ ze stałym zbiorem możliwych wartości, czyli przypadków: enum Status { case Active; case Banned; }. Przypadku używasz jako Status::Active, a parametr z typem Status nie przyjmie niczego innego. Enum backed, enum Status: string, dodatkowo daje każdemu przypadkowi wartość, którą możesz zapisać i przekonwertować z powrotem przez Status::from().
Przed enumami to samo było listą stałych tekstowych i nic nie powstrzymywało literówki w rodzaju 'actve' przed trafieniem do bazy danych. Z Status jako typem parametru można przekazać tylko trzy przypadki.
Enumy czyste i backed
Enum czysty ma przypadki, które są tylko nazwami. Enum backed deklaruje typ po nazwie, int albo string, a każdy przypadek musi wtedy mieć unikalną wartość tego typu. Każdy przypadek ma ->name; tylko przypadki backed mają ->value.
Wybierz enum backed zawsze, gdy wartość wychodzi poza program: kolumna w bazie danych, adres URL, pole formularza, JSON. Wybierz enum czysty dla wartości istniejących tylko w kodzie, takich jak stan parsera.
Konwersja wartości przez from() i tryFrom()
Enumy backed dostają dwie metody statyczne do zamiany zapisanej wartości z powrotem na przypadek. from() rzuca ValueError dla nieznanej wartości; tryFrom() zwraca null, co dobrze łączy się z ?? dla wartości domyślnej:
Używaj tryFrom() na wszystkim, co przysłał ci użytkownik, a from() na wartościach zapisanych przez twój własny kod, gdzie nieznana wartość oznacza błąd, o którym chcesz wiedzieć. Argument podlega zwykłym zasadom typów parametrów: w enumie int Priority::from('5') zwraca w trybie domyślnym Priority::Normal, bo '5' jest najpierw zamieniane na 5, Priority::from('5x') to TypeError, a przy declare(strict_types=1) każdy string to TypeError. Dotyczy to też tryFrom(): Priority::tryFrom('abc') rzuca wyjątek zamiast zwrócić null, więc dane z formularza dla enuma int najpierw sprawdź przez filter_var($raw, FILTER_VALIDATE_INT).
Lista wszystkich przypadków przez cases()
Enum::cases() zwraca tablicę wszystkich przypadków w kolejności deklaracji. Tak budujesz listę rozwijaną, walidujesz listę albo pobierasz wszystkie wartości przez array_column:
Uruchom, wybierz plan i naciśnij Choose: ten sam skrypt uruchomi się ponownie z wypełnionym $_POST['plan'], a tryFrom() zamieni przesłany string z powrotem na przypadek Plan. Podrobiona wartość, taka jak plan=gold, daje null i żadna opcja nie jest zaznaczona.
Metody, stałe i interfejsy enumów
Enumy mogą mieć metody, metody statyczne i stałe oraz implementować interfejsy. W metodzie $this to bieżący przypadek, dlatego match ($this) to naturalny sposób na przypisanie danych do każdego przypadku. Enum nie może mieć tylko właściwości: dane przypadków pochodzą z metod.
Enumy w match
match porównuje przez ===, a przypadek enuma jest identyczny tylko sam ze sobą, więc match i enumy dobrze do siebie pasują. Jeśli zapomnisz o przypadku, a ten przypadek trafi do match, PHP rzuci UnhandledMatchError zamiast po cichu nic nie zwrócić:
Czym match różni się od switch, opisuje strona match.
Enumy w JSON i jako stringi
json_encode() zapisuje przypadek backed jako jego wartość. Enuma czystego nie da się zakodować, a echo dowolnego przypadku kończy się błędem, bo enum to obiekt, a nie string. Zamiast tego wypisz ->value albo ->name:
echo Role::Admin; rzuca Error („Object of class Role could not be converted to string”), a enumy nie mogą implementować __toString(). W drugą stronę JSON daje zwykły string, więc przekonwertuj go przez from() albo tryFrom(), jak pokazano. Więcej o kodowaniu na stronie json_encode.
Częste błędy z enumami
Trzy błędy pojawiają się raz po raz. Przypadek nigdy nie jest równy swojej wartości, przypadek nie może być kluczem tablicy, a new nie działa na enumie:
Jeśli potrzebujesz mapy z kluczami będącymi samymi przypadkami, użyj SplObjectStorage albo WeakMap, które przyjmują obiekty jako klucze.
Najczęściej zadawane pytania
Jak pobrać wartość enuma w PHP?
W enumie backed odczytaj ->value: Status::Active->value to 'active'. Każdy przypadek ma też ->name, nazwę przypadku jako string ('Active'). Enum czysty (bez : string ani : int) ma tylko ->name.
Czym różni się from() od tryFrom() w enumach PHP?
Obie zamieniają wartość na przypadek enuma backed. Status::from('active') zwraca przypadek albo rzuca ValueError, gdy żaden przypadek nie ma tej wartości; Status::tryFrom('nope') zwraca wtedy null. Używaj tryFrom() dla danych od użytkownika, a from(), gdy zła wartość oznacza błąd w kodzie.
Jak pobrać wszystkie wartości enuma w PHP?
Status::cases() zwraca każdy przypadek w kolejności deklaracji. Dla wartości enuma backed użyj array_column(Status::cases(), 'value'), a dla nazw array_column(Status::cases(), 'name').
Czym różni się enum czysty od enuma backed?
Enum czysty (enum Suit { case Hearts; }) ma przypadki, które są tylko nazwami. Enum backed (enum Suit: string { case Hearts = 'H'; }) daje każdemu przypadkowi unikalną wartość int lub string, potrzebną, aby zapisać go w bazie danych, umieścić w formularzu lub JSON i przekonwertować z powrotem przez from() albo tryFrom().
Czy enum w PHP może mieć metody?
Tak. Enumy mogą mieć metody, metody statyczne i stałe oraz implementować interfejsy. W metodzie $this to bieżący przypadek, więc return match ($this) { self::Active => 'green', self::Banned => 'red' }; to częsty wzorzec. Enumy nie mogą mieć właściwości.