Enums gebruiken in PHP 8.1

0
180

PHP 8.1 zal eindelijk taalondersteuning voor opsommingen toevoegen. Enums, een afkorting voor opsommingen, zijn typen die alleen kunnen worden geïnstantieerd met specifieke waarden. Ze worden vaak aangetroffen in andere objectgeoriënteerde talen, maar er waren eerder userland-oplossingen nodig om ze in PHP te implementeren.

Basissyntaxis

Hier&#8217 ;s hoe een eenvoudige opsomming eruit ziet:

enum PostStatus { zaak Gepubliceerd; geval InReview; zaak Ontwerp; }

Het sleutelwoord case, voorheen onderdeel van switch-statements, wordt gebruikt om de specifieke waarden af ​​te bakenen die de enum accepteert. Er wordt op dezelfde manier naar waarden verwezen als naar klasseconstanten:

$published = PostStatus::Gepubliceerd;

Enums gedragen zich op dezelfde manier als klassen en interfaces. Ze zijn volledig compatibel met het typesysteem, dus je kunt aangeven dat een functie alleen een waarde accepteert die is gedefinieerd in een opsomming:

class BlogPost {   publieke functie __construct( public string $Headline, public string $Content, public PostStatus $Status=PostStatus::Draft) {}   }

Hier is een voorbeeld van het gebruik van de BlogPost-klasse:

//OK $post = nieuwe BlogPost( “Voorbeeldbericht”, “Een voorbeeld”, PostStatus::Concept );   //TypeError: Argument #3 ($Status) moet van het type PostStatus $post = new BlogPost( “Gebroken voorbeeld”, “Een gebroken voorbeeld”, “Ingediend” );

De eerste instantie werkt omdat de $Status een geldige waarde is uit de PostStatus-enum. In het tweede geval wordt een gewone tekenreeks doorgegeven als $Status, wat niet is toegestaan ​​omdat de waarde moet worden gedefinieerd in PostStatus.

Enum-gevallen worden weergegeven als constanten op het enum-object. Dit betekent dat u ze kunt gebruiken als statische waarden en als onderdeel van constante expressies. De BlogPost-constructor toont een opsomming die wordt gebruikt als een standaardparameterwaarde, waarbij $Status automatisch wordt ingesteld op Draft als de beller geen waarde heeft opgegeven.

Advertentie

U hebt toegang tot alle beschikbare waarden in een opsomming met behulp van de case-methode:

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

Pure vs Backed Enums

De PostStatus-enum hierboven is een pure opsomming. Het bevat alleen case-statements, zonder extra gegevens. PHP laat je ook een waarde toekennen aan enum-cases, waardoor een geback-upte enum ontstaat.

enum PostStatus : string { zaak Gepubliceerd = "S1"; geval InReview = "S2"; geval Draft = "S3"; }

Hier is de PostStatus-enum gewijzigd om een ​​ondersteunde opsomming te maken. De typhint in de definitie van de opsomming bepaalt dat aan elk geval een tekenreekswaarde is toegewezen. In dit voorbeeld gaan we ervan uit dat elke benoemde poststatus een bijbehorende korte identifier heeft. Het kan deze identifier zijn die in de database wordt opgeslagen wanneer posts worden bewaard.

U kunt ondersteunde waarden openen via de value-eigenschap op case-instanties:

class BlogPostRepository {   openbare functie opslaan(BlogPost $Post) : ongeldig { $dit -> invoegen( "blog_posts", [ “kop” => $Post -> Kop, "inhoud" => $Post -> Inhoud, "status" => $Post -> Status -> waarde ] ); }   }   $post = nieuwe BlogPost("Example", "Demo", PostStatus::Gepubliceerd); (nieuwe BlogPostRepository()) -> opslaan($post);

In dit voorbeeld zou de waarde van het persistente statusveld worden ingesteld op S1, gebaseerd op de ondersteunde versie van de PostStatus-enum die hierboven is weergegeven.

Gesteunde opsommingen accepteren alleen tekenreeksen en gehele getallen als waarden. Het is ook niet mogelijk om het union-type string|int te gebruiken. Bovendien heeft elk geval een unieke waarde nodig – het volgende voorbeeld is niet toegestaan:

enum PostStatus : string {   zaak Gepubliceerd = "S1"; geval Draft = "S1";   } Advertentie

PHP biedt een hulpprogramma-methode voor enums om een ​​instantie te maken van een ondersteunde waarde:

//haal de blogpost van eerder uit de database //de "status" veld = S1 $status = PostStatus::from($record["status"]);

De methode from() hydrateert instanties uit waardegevallen. In dit voorbeeld wordt S1 teruggekoppeld naar de casus Gepubliceerd en ontvangt uw code een exemplaar van PostStatus::Published.

from() genereert een ValueError als de invoerwaarde ongeldig is; in scenario's waarin u weet dat de waarde mogelijk niet bruikbaar is, kan in plaats daarvan de alternatieve methode tryFrom() worden gebruikt. Dit retourneert null wanneer er geen overeenkomst is, in plaats van de fout te gooien.

Methoden toevoegen aan Enums

Omdat enums zijn gebaseerd op klassen, kunt u er ook methoden aan toevoegen!

enum PostStatus {   zaak Gepubliceerd; zaak Ontwerp;   publieke functie isPubliclyAccessible() : bool { return ($this instanceof self::Published); }   }

Hierdoor kunt u case-specifiek gedrag binnen uw opsomming houden, in plaats van het over uw codebase te dupliceren.

Enums kan ook interfaces implementeren:

enum PostStatus implementeert PublicAccessGatable {   zaak Gepubliceerd; zaak Ontwerp;   publieke functie isPubliclyAccessible() : bool { return ($this instanceof self::Published); }   }

Je kunt nu een PostStatus-instantie doorgeven aan alles dat een PublicAccessGatable accepteert:

klasse UserAuthenticator {   functie shouldAllowAccess(PublicAccessGatable $Resource) : bool { retourneer ($this -> Gebruiker -> isAdmin() || $Bron -> isPubliclyAccessible()); }   }   $auth = nieuwe UserAuthenticator();   //haal een blogbericht uit de database als (!$auth -> shouldAllowAccess($post -> Status)) { http_response_code(403); } Advertentie

Er zijn geen beperkingen op wat u kunt doen met enum-methoden – het zijn tenslotte reguliere PHP-methoden – maar over het algemeen zou je verwachten dat ze een soort vergelijking zouden maken met het geval van de instantie, en dan een statische waarde teruggeven. Enums kunnen traits gebruiken, dus je kunt bestaande methoden die je op deze manier hebt geabstraheerd, ook gebruiken.

Je kunt openbare, beschermde en privé-methoden gebruiken in enums, hoewel beschermd en privé hetzelfde hebben effect. Enums kunnen elkaar niet uitbreiden, dus privé is in feite overbodig. U kunt ook geen constructor of destructor toevoegen. Statische methoden worden ondersteund en kunnen worden aangeroepen op de enum-klasse of zijn case-instanties.

Constanten

Enums kunnen ook hun eigen constanten hebben, hetzij als gewone letterlijke waarden of als verwijzing naar een enum-geval:

enum PostStatus {   zaak Gepubliceerd; zaak Ontwerp;   public const Live = zelf::Gepubliceerd; public const PlainConstant = "foobar";   }

Dit kan verwarring veroorzaken omdat dezelfde syntaxis wordt gebruikt voor toegang tot cases (enum-instanties) en constanten:

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

Alleen $published zou voldoen aan een PostStatus-typehint, aangezien $plain verwijst naar een eenvoudige scalaire waarde.

Wanneer Enums gebruiken?

Enums zijn voor gelegenheden waar je flexibiliteit nodig hebt in de waarde die een variabele kan aannemen, maar alleen in een vooraf bepaalde reeks mogelijke gevallen.

Advertentie

De blogpostklasse die door dit bericht wordt geleid, is een klassiek voorbeeld. Berichten kunnen zich alleen in een van een bekende reeks toestanden bevinden, maar PHP had voorheen geen eenvoudige manier om dit te bereiken.

In oudere versies zou u deze benadering hebben gebruikt:

class PostStatus { const Gepubliceerd = 0; const Diepgang = 1; }   klasse BlogPost { publieke functie __construct( public string $Headline, public int $Status ) {} }   $post = nieuwe BlogPost("Mijn kop", PostStatus::Gepubliceerd);

Het probleem hier is dat $Status eigenlijk elk geheel getal accepteert, dus de volgende aanroep zou perfect geldig zijn:

$post = nieuwe BlogPost("Mijn kop", 9000);

Bovendien staan ​​BlogPost en PostStatus volledig los van elkaar – er is geen manier waarop iemand die BlogPost leest het bereik van waarden kan leren die $Status daadwerkelijk accepteert. Hoewel deze problemen kunnen worden verholpen door gebruik te maken van de juiste typehints van docblock, of “nep-enum” pakketten, ze voegen allemaal extra lagen toe rond een concept dat andere programmeertalen eenvoudig maken.

Het toevoegen van native enums aan PHP is een stap die helpt om het typesysteem van de taal af te ronden. U kunt eindelijk toegestane waarden typen op een manier die iedereen op dezelfde pagina houdt. Als u een ongeldige waarde doorgeeft, krijgt u een runtime-fout. Uw IDE kan u beter helpen bij het opgeven van de juiste waarden, aangezien hij weet dat $Status slechts drie opties accepteert, in plaats van “een geheel getal.”

Conclusion< /h2>

Enums behandelen enkele veelvoorkomende pijnpunten van ontwikkelaars bij het werken in PHP. Ze maken het mogelijk om aan te geven dat parameters, retourwaarden en eigenschappen deel moeten uitmaken van een reeks vooraf bepaalde opties.

Enums zijn flexibele codebase-entiteiten die u in pure vorm eenvoudig kunt houden of uitbreiden met ondersteunde waarden , interface-implementaties en aangepaste methoden. Enums gedragen zich in de meeste gevallen op dezelfde manier als gewone objecten en ondersteunen klassefuncties zoals __call(), __invoke en ::class.

Advertentie

U kunt enums introspecteren met de nieuwe enum_exists() functie en ReflectionEnum Reflectie klasse. Bovendien implementeren enums twee nieuwe interfaces, UnitEnum (in het geval van pure enums) en BackedEnum (voor opsommingen met back-waarden). Deze kunnen worden gebruikt in generieke kadercode die met elke enum werkt. De interfaces kunnen niet handmatig worden geïmplementeerd door userland-code.

Enums komt in PHP terecht als onderdeel van de 8.1-release in november 2021. Ze zijn al beschikbaar in de nieuwste bètaversies. PHP 8.1 levert ook verschillende andere gemaksfuncties, waaronder alleen-lezen-eigenschappen en kruispunttypen.