• Czas czytania ~5 min
  • 07.03.2023

Korzystasz z przestarzałej aplikacji Laravel? Uzyskaj natychmiastowe, zautomatyzowane aktualizacje Laravel dzięki Laravel Shift

W końcu nadchodzą — wbudowana obsługa wyliczeń zostanie dodana w PHP 8.1! Niektórzy mogą uważać je za już dawno spóźnione, ale nie słyszysz, jak narzekam; Cieszę się, że im się udało! Ten post poświęcony jest dogłębnemu przyjrzeniu się nowo dodanej funkcji. Jeśli chcesz być na bieżąco z tego rodzaju zmianami i nowymi funkcjami w PHP, zapisz się do mojego newslettera.

Jak zwykle w przypadku moich postów z funkcjami PHP, zaczynamy od ogólnego przeglądu tego, jak wyglądają wyliczenia:Zaletą wyliczeń jest to, że reprezentują one zbiór stałych wartości, ale co najważniejsze, wartości te można wpisać, w następujący sposób:W tym przykładzie tworzenie wyliczenia i przekazywanie go do wygląda BlogPost następująco:

enum Status
{
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
}

class BlogPost
{
    public function __construct(
        public Status $status, 
    ) {}
}

$post = new BlogPost(Status::DRAFT);

To podstawy, jak widać, nie ma w nich nic skomplikowanego. Jest jednak wiele notatek pobocznych, spójrzmy na enums dogłębnie!

# Metody

wyliczenia Wyliczenie może definiować metody, podobnie jak klasy. Jest to bardzo potężna funkcja, szczególnie w połączeniu z operatoremmatch:Metody mogą być używane w następujący sposób:Metody statyczne są również dozwolone:I można również używać self w enum:# Interfejsy

enum Status
{
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
    
    public function color(): string
    {
        return match($this) 
        {
            Status::DRAFT => 'grey',   
            Status::PUBLISHED => 'green',   
            Status::ARCHIVED => 'red',   
        };
    }
}

Enum Enums mogą implementować interfejsy, podobnie jak normalne klasy:

$status = Status::ARCHIVED;
$status->color(); // 'red'

enum Status
{
    // …
    
    public static function make(): Status
    {
        // …
    }
}

enum Status
{
    // …
    
    public function color(): string
    {
        return match($this) 
        {
            self::DRAFT => 'grey',   
            self::PUBLISHED => 'green',   
            self::ARCHIVED => 'red',   
        };
    }
}

interface HasColor
{
    public function color(): string;
}
enum Status implements HasColor
{
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
    
    public function color(): string { /* … */ }
}

# Wartości wyliczenia — aka "Wspierane wyliczenia"

Wartości wyliczenia są reprezentowane wewnętrznie przez obiekty, ale w razie potrzeby można przypisać im wartość; Jest to przydatne dla np. serializacja ich do bazy danych.

enum Status: string
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
}

Odnotować deklarację typu w definicji wyliczenia. Wskazuje, że wszystkie wartości wyliczenia są danego typu. Możesz także zrobić z tego plik int. Należy pamiętać, że tylko int i string są dozwolone jako wartości wyliczenia.

enum Status: int
{
    case DRAFT = 1;
    case PUBLISHED = 2;
    case ARCHIVED = 3;
}

Termin techniczny dla wyliczeń pisanych nazywa się "wyliczeniami wspieranymi", ponieważ są one "wspierane" przez prostszą wartość. Jeśli zdecydujesz się przypisać wartości wyliczenia, wszystkie przypadki powinny mieć wartość. Nie można ich mieszać i dopasowywać. Enums, które nie są "wspierane", nazywane są "czystymi wyliczeniami".

# Enum z interfejsami Jeśli łączysz wyliczenia z interfejsem

, typ wyliczenia musi znajdować się bezpośrednio po nazwie wyliczenia, przed słowem kluczowymimplements.

enum Status: string implements HasColor
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
    
    // …
}

# Serializacja wyliczeń z podłożem

Jeśli przypisujesz wartości do przypadków wyliczenia, prawdopodobnie potrzebujesz sposobu ich serializacji i deserializacji. Serializacja oznacza, że potrzebujesz sposobu na dostęp do wartości wyliczenia. Odbywa się to za pomocą właściwości publicznej tylko do odczytu:Przywracanie wyliczenia z wartości można wykonać za pomocą Enum::from:

$value = Status::PUBLISHED->value; // 2

$status = Status::from(2); // Status::PUBLISHED

There jest również zwracanetryFrom, null jeśli zostanie przekazana nieznana wartość. Gdybyś użyłfrom, byłby wyjątek.

$status = Status::from('unknown'); // ValueError
$status = Status::tryFrom('unknown'); // null

Zauważ, że możesz również użyć wbudowanych serialize funkcji i funkcji unserialize na wyliczeniach. Ponadto można używać json_encode w połączeniu z wyliczeniami wspieranymi, jego wynikiem będzie wartość wyliczenia. To zachowanie można zastąpić, implementując JsonSerializable.

# Wyświetlanie listy wartości wyliczenia Możesz użyć metody statycznejEnum::cases(), aby uzyskać listę wszystkich dostępnych przypadków w enum:Zauważ, że ta tablica zawiera rzeczywiste obiekty wyliczenia:

Status::cases();
/* [
    Status::DRAFT, 
    Status::PUBLISHED, 
    Status::ARCHIVED
] */

# Wyliczenia są obiektami Wspomniałem już, że wartości

array_map(
    fn(Status $status) => $status->color(), 
    Status::cases()
);

wyliczeń są reprezentowane jako obiekty

, w rzeczywistości są to obiekty singleton. Oznacza to, że możesz robić z nimi porównania w następujący sposób:

$statusA = Status::PENDING;
$statusB = Status::PENDING;
$statusC = Status::ARCHIVED;
$statusA === $statusB; // true
$statusA === $statusC; // false
$statusC instanceof Status; // true

# Wyliczenia jako klucze

tablicowe Ponieważ wartości wyliczeń są w rzeczywistości obiektami, obecnie nie można ich używać jako kluczy tablicowych. Następujący błąd spowoduje błąd:

$list = [
    Status::DRAFT => 'draft',
    // …
];

Istnieje RFC, aby zmienić to zachowanie, ale nie zostało ono jeszcze przegłosowane.

Oznacza to, że możesz używać wyliczeń tylko jako kluczy wejściowych SplObjectStorage i WeakMaps.

#

Cechy Wyliczenie może używać cech tak jak klasy, ale z pewnymi ograniczeniami. Nie wolno nadpisywać wbudowanych metod wyliczenia i nie mogą one zawierać właściwości klas — są one zabronione w wyliczeniach.

# Odbicie i atrybuty

Zgodnie z oczekiwaniami dodano kilka klas refleksji do obsługi wyliczeń: ReflectionEnum, ReflectionEnumUnitCase i ReflectionEnumBackedCase. Jest też nowa enum_exists funkcja, która robi to, co sugeruje jej nazwa.

Podobnie jak normalne klasy i właściwości, wyliczenia i ich przypadki mogą być opisywane za pomocą atrybutów. Należy pamiętać, że TARGET_CLASS filtr będzie również zawierał wyliczenia.

Ostatnia rzecz: wyliczenia mają również właściwość $enum->nametylko do odczytu , o której RFC wspomina, że jest szczegółem implementacji i prawdopodobnie powinna być używana tylko do celów debugowania. Warto jednak o tym wspomnieć.

Zauważyłeś tpyo? Możesz przesłać żądanie ściągnięcia, aby to naprawić. Jeśli chcesz być na bieżąco z tym, co dzieje się na tym blogu, możesz mnie śledzić na Twitterze lub zapisz się do mojego newslettera:

To wszystko, co można powiedzieć o wyliczeniach, nie mogę się doczekać, aby z nich korzystać, gdy tylko pojawi się PHP 8.1, a także na wygaśnięcie mojej własnej implementacji przestrzeni użytkownika.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

O

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

O autorze CrazyBoy49z
WORK EXPERIENCE
Kontakt
Ukraine, Lutsk
+380979856297