So verwenden Sie Aufzählungen in PHP 8.1

0
229

PHP 8.1 wird endlich Sprachunterstützung für Enumerationen hinzufügen. Aufzählungen, kurz für Aufzählungen, sind Typen, die nur mit bestimmten Werten instanziiert werden können. Sie sind häufig in anderen objektorientierten Sprachen zu finden, erforderten jedoch zuvor Userland-Workarounds, um sie in PHP zu implementieren.

Grundsyntax

Hier&#8217 ;so sieht eine einfache Aufzählung aus:

enum PostStatus { Fall veröffentlicht; Fall InReview; Fall Entwurf; }

Das Schlüsselwort case, das früher Teil von switch-Anweisungen war, wird verwendet, um die spezifischen Werte abzugrenzen, die die Aufzählung akzeptiert. Werte werden wie Klassenkonstanten referenziert:

$veröffentlicht = PostStatus::Veröffentlicht;

Enums verhalten sich ähnlich wie Klassen und Interfaces. Sie sind vollständig mit dem Typsystem kompatibel, sodass Sie angeben können, dass eine Funktion nur einen in einer Enumeration definierten Wert akzeptiert:

class BlogPost {   öffentliche Funktion __construct( öffentlicher String $Headline, öffentlicher String $Content, öffentlicher PostStatus $Status=PostStatus::Draft) {}   }

Hier ein Beispiel für die Verwendung der BlogPost-Klasse:

//OK $post = neuer BlogPost( "Beispielpost", "Ein Beispiel", PostStatus::Draft );   //TypeError: Argument #3 ($Status) muss vom Typ PostStatus sein $post = new BlogPost( "Fehlerhaftes Beispiel", "Ein fehlerhaftes Beispiel", "Eingereicht" );

Die erste Instanz funktioniert, weil ihr $Status ein gültiger Wert aus der PostStatus-Enumeration ist. Im zweiten Fall wird ein einfacher String als $Status übergeben, was verboten ist, da der Wert in PostStatus definiert werden muss.

Aufzählungsfälle werden als Konstanten im Aufzählungsobjekt dargestellt. Dies bedeutet, dass Sie sie als statische Werte und als Teil konstanter Ausdrücke verwenden können. Der BlogPost-Konstruktor zeigt einen Enumerationsfall, der als Standardparameterwert verwendet wird, wobei $Status automatisch auf Entwurf gesetzt wird, wenn kein Wert vom Aufrufer bereitgestellt wird.

Werbung

Sie können auf alle verfügbaren Werte zugreifen in einer Aufzählung mit der Case-Methode:

PostStatus::cases(); //[PostStatus::Published, PostStatus::InReview, PostStatus::Draft]

Pure vs. Backed Enums

Die PostStatus-Enumeration oben ist eine reine aufzählen. Es enthält nur case-Anweisungen ohne zusätzliche Daten. Mit PHP können Sie auch Aufzählungsfällen einen Wert zuweisen, wodurch eine gesicherte Aufzählung erstellt wird.

enum PostStatus : string { Fall veröffentlicht = “S1”; Fall InReview = “S2”; Fall Entwurf = “S3”; }

Hier wurde die PostStatus-Aufzählung geändert, um eine gesicherte Aufzählung zu erstellen. Der typehint in der enum-Definition legt fest, dass jedem Fall ein Zeichenfolgenwert zugewiesen ist. In diesem Beispiel gehen wir davon aus, dass jeder Named Post-Status eine zugeordnete Kurzkennung hat. Es könnte dieser Bezeichner sein, der in der Datenbank gespeichert wird, wenn Beiträge persistiert werden.

Sie können auf gesicherte Werte über die value-Eigenschaft von Fallinstanzen zugreifen:

Klasse BlogPostRepository {   öffentliche Funktion save(BlogPost $Post) : nichtig { $dies -> einfügen( "blog_posts", [ "Überschrift" => $Beitrag -> Überschrift, "Inhalt" => $Beitrag -> Inhalt, "Status" => $Beitrag -> Status -> Wert ] ); }   }   $post = new BlogPost("Beispiel", "Demo", PostStatus::Published); (neues BlogPostRepository()) -> speichern($post);

In diesem Beispiel würde der Wert des persistenten Statusfelds auf S1 gesetzt, basierend auf der gesicherten Version der oben gezeigten PostStatus-Enum.

Unterstützte Enumerationen akzeptieren nur Zeichenfolgen und Ganzzahlen als Werte. Es ist auch nicht möglich, den Union-Typ string|int zu verwenden. Außerdem benötigt jeder Fall einen eindeutigen Wert – das folgende Beispiel ist nicht zulässig:

enum PostStatus : string {   Fall veröffentlicht = “S1”; Fall Entwurf = “S1”;   } Werbung

PHP bietet eine Dienstprogrammmethode für Enumerationen, um eine Instanz aus einem gesicherten Wert zu erstellen:

//den Blogbeitrag von früher aus der Datenbank holen //der "status" Feld = S1 $status = PostStatus::from($record["status"]);

Die from()-Methode hydratisiert Instanzen aus Wertfällen. In diesem Beispiel wird S1 wieder dem Fall “Published” zugeordnet, und Ihr Code empfängt eine Instanz von PostStatus::Published.

from() löst einen ValueError aus, wenn der Eingabewert ungültig ist; In Szenarien, in denen Sie wissen, dass der Wert möglicherweise nicht verwendet werden kann, kann stattdessen die alternative Methode tryFrom() verwendet werden. Dies gibt null zurück, wenn es keine Übereinstimmung gibt, anstatt den Fehler auszulösen.

Methoden zu Aufzählungen hinzufügen

Da Aufzählungen auf Klassen basieren, können Sie ihnen auch Methoden hinzufügen!

enum PostStatus {   Fall veröffentlicht; Fall Entwurf;   öffentliche Funktion isPubliclyAccessible() : bool { ($this instanceof self::Published); }   }

Auf diese Weise können Sie fallspezifisches Verhalten in Ihrer Enumeration beibehalten, anstatt es in Ihrer Codebasis zu duplizieren.

Enums können auch Schnittstellen implementieren:

enum PostStatus implementiert PublicAccessGatable {   Fall veröffentlicht; Fall Entwurf;   öffentliche Funktion isPubliclyAccessible() : bool { ($this instanceof self::Published); }   }

Jetzt können Sie eine PostStatus-Instanz an alles übergeben, das ein PublicAccessGable akzeptiert:

Klasse UserAuthenticator {   Funktion sollteAllowAccess(PublicAccessGatable $Ressource) : bool { ($this -> Benutzer -> isAdmin() || $Ressource -> istÖffentlichzugänglich()); }   }   $auth = neuer UserAuthenticator();   //einen Blog-Beitrag aus der Datenbank abrufen, wenn (!$auth -> sollteZugriff erlauben($post -> Status)) { http_response_code(403); } Werbung

Es gibt keine Einschränkungen bezüglich der Möglichkeiten mit Enumerationsmethoden – sie sind schließlich normale PHP-Methoden – Im Allgemeinen würden Sie jedoch erwarten, dass sie eine Art Vergleich mit dem Fall der Instanz durchführen und dann einen statischen Wert zurückgeben. Aufzählungen können Merkmale verwenden, sodass Sie auch vorhandene Methoden, die Sie auf diese Weise abstrahiert haben, einbinden können.

Sie können öffentliche, geschützte und private Methoden in Aufzählungen verwenden, obwohl protected und private dasselbe haben Wirkung. Enums können sich nicht gegenseitig erweitern, sodass private effektiv überflüssig ist. Sie können auch keinen Konstruktor oder Destruktor hinzufügen. Statische Methoden werden unterstützt und können für die Enum-Klasse oder ihre Case-Instanzen aufgerufen werden.

Konstanten

Enums können auch ihre eigenen Konstanten haben, entweder als reguläre Literalwerte oder als Verweis auf einen Enum-Fall:

enum PostStatus {   Fall veröffentlicht; Fall Entwurf;   public const Live = self::Published; public const PlainConstant = "foobar";   }

Dies kann zu Verwirrung führen, da dieselbe Syntax für den Zugriff auf Fälle (Aufzählungsinstanzen) und Konstanten verwendet wird:

$published = PostStatus::Published; $plain = PostStatus::PlainConstant;

Nur $published würde einen PostStatus-Typhint erfüllen, da sich $plain auf einen einfachen Skalarwert bezieht.

Wann sollten Enums verwendet werden?

Enums sind für Fälle gedacht, in denen Sie Flexibilität beim Wert benötigen, den eine Variable annehmen kann, jedoch nur innerhalb einer vordefinierten Gruppe möglicher Fälle.

Werbung

Die Blogpost-Klasse, die diesen Post durchläuft, ist ein klassisches Beispiel. Beiträge können sich nur in einem bekannten Satz von Zuständen befinden, aber PHP hatte zuvor keine einfache Möglichkeit, dies zu erreichen.

In älteren Versionen haben Sie möglicherweise diesen Ansatz verwendet:

class PostStatus { const Veröffentlicht = 0; const Entwurf = 1; }   Klasse BlogPost { öffentliche Funktion __construct( public string $Headline, public int $Status ) {} }   $post = new BlogPost("Meine Überschrift", PostStatus::Published);

Das Problem hierbei ist, dass $Status tatsächlich jede ganze Zahl akzeptiert, daher wäre der folgende Aufruf vollkommen gültig:

$post = neuer BlogPost("Meine Überschrift", 9000);

Außerdem sind BlogPost und PostStatus vollständig getrennt – Es gibt keine Möglichkeit, dass jemand, der BlogPost liest, den Wertebereich erfahren kann, den $Status tatsächlich akzeptiert. Während diese Probleme durch die Verwendung geeigneter Docblock-Typhinweise oder “fake enum” Pakete hinzufügen, fügen sie alle zusätzliche Schichten um ein Konzept hinzu, das andere Programmiersprachen einfach machen.

Das Hinzufügen von nativen Enumerationen zu PHP ist ein Schritt, der das Typsystem der Sprache abrundet. Endlich können Sie zulässige Werte so eingeben, dass alle auf dem gleichen Stand bleiben. Wenn Sie einen ungültigen Wert übergeben, erhalten Sie einen Laufzeitfehler. Ihre IDE kann Sie bei der Bereitstellung korrekter Werte besser unterstützen, da sie weiß, dass $Status nur drei Optionen akzeptiert, anstatt “beliebige ganze Zahlen.”

Schlussfolgerung< /h2>

Enums adressieren einige häufige Entwicklerprobleme bei der Arbeit in PHP. Sie ermöglichen den Tipp, dass Parameter, Rückgabewerte und Eigenschaften zu einer Reihe von vordefinierten Optionen gehören müssen.

Enums sind flexible Codebasis-Entitäten, die Sie in reiner Form einfach halten oder mit unterstützten Werten erweitern können , Schnittstellenimplementierungen und benutzerdefinierte Methoden. Aufzählungen verhalten sich in den meisten Fällen ähnlich wie normale Objekte und unterstützen Klassenfunktionen wie __call(), __invoke und ::class.

Werbung

Sie können Aufzählungen mit der neuen Funktion enum_exists() und ReflectionEnum überprüfen Reflexionsklasse. Außerdem implementieren Aufzählungen zwei neue Schnittstellen, UnitEnum (bei reinen Aufzählungen) und BackedEnum (für Aufzählungen mit gesicherten Werten). Diese können in generischem Framework-Code verwendet werden, der mit jeder Enumeration funktioniert. Die Schnittstellen können nicht manuell durch Userland-Code implementiert werden.

Enums werden im November 2021 als Teil der Version 8.1 in PHP landen. Sie sind bereits in den neuesten Beta-Builds verfügbar. PHP 8.1 wird auch mehrere andere Komfortfunktionen liefern, einschließlich schreibgeschützter Eigenschaften und Kreuzungstypen.