Hur man använder enums i PHP 8.1

0
159

PHP 8.1 kommer äntligen att lägga till språkstöd för enums. Enums, kort för uppräkningar, är typer som bara kan instanseras med specifika värden. De finns vanligtvis på andra objektorienterade språk men har tidigare krävt lösningar på användarland för att implementera i PHP.

Basic Syntax

Here &#8217 ; hur ser en enkel enum ut:

enum PostStatus { fall Publicerat; fall InReview; fall Utkast; }

Fallordet, tidigare en del av switch -satser, används för att avgränsa de specifika värden som enum accepterar. Värden refereras på samma sätt som klasskonstanter:

$ publish = PostStatus :: Published;

Enums beter sig på samma sätt som klasser och gränssnitt. De är helt kompatibla med typsystemet, så du kan skriva antydningar om att en funktion endast accepterar ett värde som definieras i enum:

class BlogPost { & nbsp; offentlig funktion __konstruera ( public string $ Headline, public string $ Content, public PostStatus $ Status = PostStatus :: Utkast ) { } & nbsp; }

Här är ett exempel på hur du använder BlogPost -klassen:

//OK $ post = nytt BlogPost ( & quot; Exempel inlägg & quot ;, & quot; Ett exempel & quot ;, PostStatus :: Utkast &#41 ;; & nbsp; //TypeError: Argument #3 ($ Status) måste vara av typen PostStatus $ post = new BlogPost & #40; “Brutet exempel”, “Ett trasigt exempel”, “skickat” &#41 ;;

Den första instansen fungerar eftersom dess $ Status är ett giltigt värde från PostStatus -enum. I det andra fallet skickas en vanlig sträng som $ Status, vilket är förbjudet eftersom värdet måste definieras inom PostStatus.

Enum -fall representeras som konstanter på enum -objektet. Det betyder att du kan använda dem som statiska värden och som en del av konstanta uttryck. BlogPost -konstruktören visar ett enum -fall som används som standardparametervärde, där $ Status automatiskt ställs in på Utkast när inget värde tillhandahålls av den som ringer.

Annons

Du kan komma åt alla tillgängliga värden i en enum med sin case -metod:

PostStatus :: fall ( &#41 ;; //[PostStatus :: Published, PostStatus :: InReview, PostStatus :: Draft]

Pure vs Backed Enums

PostStatus enum ovan är en ren enum. Den innehåller endast ärendebesked, utan extra data. PHP låter dig också fästa ett värde på enum -fall och skapa en backad enum.

enum PostStatus: string { fall Publicerat = & quot; S1 & quot ;; fall InReview = & quot; S2 & quot ;; fall Utkast = & quot; S3 & quot ;; }

Här har PostStatus -enum ändrats för att skapa en backad enum. Typhintet i enums definition föreskriver att varje fall har ett strängvärde tilldelat det. I det här exemplet antar vi att varje namngiven poststatus har en tillhörande kort identifierare. Det kan vara den här identifieraren som sparas i databasen när inlägg kvarstår.

Du kan komma åt värden som säkerhetskopieras via värdeegenskapen på fallinstanser:

klass BlogPostRepository { & nbsp; allmän funktion spara ( BlogPost $ Post ) : void { $ detta -& gt; infoga ( & quot; blog_posts & quot ;, [ & quot; rubrik & quot; = & gt; $ Post -& gt; Rubrik, & quot; innehåll & quot; = & gt; $ Post -& gt; Innehåll, & quot; status & quot; = & gt; $ Post -& gt; Status -& gt; värde ] &#41 ;; } & nbsp; } & nbsp; $ post = ny BlogPost ( & quot; Exempel & quot ;, & quot; Demo & quot ;, PostStatus :: Publicerad &#41 ;; ( nytt BlogPostRepository ( ) ) -& gt; spara ( $ post &#41 ;;

Detta exempel skulle sätta värdet för det kvarstående statusfältet till S1, baserat på den backade versionen av PostStatus -enum som visas ovan.

Säkerhetskopierade accepterar endast strängar och heltal som värden. Det går inte heller att använda unionstypsträngen | int. Dessutom behöver varje fall ett unikt värde – följande exempel är inte tillåtet:

enum PostStatus: string { & nbsp; fall Publicerat = & quot; S1 & quot ;; fall Utkast = & quot; S1 & quot ;; & nbsp; } Annons

PHP tillhandahåller en verktygsmetod i enums för att skapa en instans från ett backat värde:

//hämta blogginlägget från tidigare från databasen //statusen & quot; field = S1 $ status = PostStatus :: från ( $ record [ & quot; status & quot; ] &#41 ;;

Metoden from () hydrerar instanser från värdefall. I det här exemplet mappas S1 tillbaka till det publicerade fallet och din kod får en instans av PostStatus :: Published.

från () kastar ett ValueError om inmatningsvärdet är ogiltigt; i scenarier där du vet att värdet kanske inte är användbart kan den alternativa metoden tryFrom () användas istället. Detta returnerar noll när det inte finns någon match, istället för att kasta felet.

Lägga till metoder i listor

Eftersom enum är baserade på klasser kan du också lägga till metoder till dem!

enum PostStatus { & nbsp; fall Publicerat; fall Utkast; & nbsp; allmän funktion ärPubliclyAccessible ( ) : bool { returnera ( $ denna instans av mig själv :: Publicerad &#41 ;; } & nbsp; }

Detta låter dig behålla specifika beteenden i ditt enum, istället för att duplicera det i din kodbas.

Enums kan också implementera gränssnitt:

enum PostStatus implementerar PublicAccessGatable { & nbsp; fall Publicerat; fall Utkast; & nbsp; allmän funktion ärPubliclyAccessible ( ) : bool { returnera ( $ denna instans av mig själv :: Publicerad &#41 ;; } & nbsp; }

Nu kan du skicka en PostStatus -instans till allt som accepterar en PublicAccessGatable:

klass UserAuthenticator { & nbsp; function shouldAllowAccess ( PublicAccessGatable $ Resource ) : bool { returnera ( $ detta -& gt; Användare -& gt; isAdmin ( ) || $ Resurs -& gt; ärPublicAccessible ( ) &#41 ;; } & nbsp; } & nbsp; $ auth = new UserAuthenticator ( &#41 ;; & nbsp; //få ett blogginlägg från databasen om (! $ auth -& gt; shouldAllowAccess ( $ post -& gt; Status ) ) { http_response_code ( 403 &#41 ;; } Annons

Det finns inga begränsningar för vad du kan göra med enum -metoder – de är vanliga PHP -metoder, trots allt – men i allmänhet förväntar du dig att de ska utföra någon form av jämförelse mot instansfallet och sedan returnera ett statiskt värde. Enums kan använda egenskaper, så att du kan dra in befintliga metoder som du också har abstraherat på detta sätt.

Du kan använda offentliga, skyddade och privata metoder i enums, även om skyddade och privata har samma effekt. Enums kan inte förlänga varandra så att privat effektivt är överflödigt. Du kan inte heller lägga till en konstruktör eller destruktor. Statiska metoder stöds och kan anropas i enumklassen eller dess fallinstanser.

Konstanter

Enum kan också ha sina egna konstanter, antingen som vanliga bokstavsvärden eller som en hänvisning till ett enumfall:

enum PostStatus { & nbsp; fall Publicerat; fall Utkast; & nbsp; public const Live = self :: Publicerat; public const PlainConstant = & quot; foobar & quot ;; & nbsp; }

Detta har potential att skapa förvirring eftersom samma syntax används för att komma åt fall (enum -instanser) och konstanter:

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

Endast $ publicerade skulle tillfredsställa en PostStatus-typhint, eftersom $ plain hänvisar till ett enkelt skalvärde.

När ska man använda enums?

Enums är för tillfällen där du behöver flexibilitet i det värde en variabel kan ta, men endast bland en förutbestämd uppsättning möjliga fall.

Annonsering

Blogginläggsklassen som körs genom detta inlägg är ett klassiskt exempel. Inlägg kan bara finnas i en av en känd uppsättning stater men PHP hade tidigare inget enkelt sätt att uppnå detta.

I äldre versioner kan du ha använt detta tillvägagångssätt:

class PostStatus { const Publicerat = 0; const Utkast = 1; } & nbsp; klass BlogPost { offentlig funktion __konstruera ( public string $ Headline, public int $ Status ) { } } & nbsp; $ post = ny BlogPost ( & quot; Min rubrik & quot ;, PostStatus :: Publicerad &#41 ;;

Problemet här är att $ Status faktiskt accepterar alla heltal, så följande samtal skulle vara fullt giltigt:

$ post = ny BlogPost ( & quot; Min rubrik & quot ;, 9000 &#41 ;;

Dessutom är BlogPost och PostStatus helt fristående – det finns inget sätt att någon som läser BlogPost kan lära sig de värden som $ Status faktiskt accepterar. Även om dessa problem kan lindras genom att använda lämpliga docblock-typhints, eller tredjeparts “ fake enum ” paket, de lägger alla till extra lager kring ett koncept andra programmeringsspråk gör det enkelt.

Att lägga till inbyggda enums till PHP är ett steg som hjälper till att avrunda språkets typsystem. Du kan äntligen skriva tips om tillåtna värden på ett sätt som håller alla på samma sida. Om du passerar ett ogiltigt värde får du ett runtime -fel. Din IDE kan bättre hjälpa dig att tillhandahålla korrekta värden, eftersom den vet att $ Status endast accepterar tre alternativ, i stället för “ vilket heltal. ”

Slutsats < /h2>

Enums behandlar några vanliga utvecklarsmärtor när du arbetar i PHP. De gör det möjligt att skriva en antydan om att parametrar, returvärden och egenskaper måste vara en av en uppsättning förutbestämda alternativ.

Enum är flexibla kodbasenheter som du kan hålla enkel i ren form eller utöka med backade värden , gränssnittsimplementeringar och anpassade metoder. Enums beter sig på samma sätt som vanliga objekt i de flesta fall och stöder klassfunktioner som __call (), __invoke och :: class.

Annonsering

Du kan introspektera enum med den nya funktionen enum_exists () och ReflectionEnum Reflektionsklass. Dessutom implementerar enums två nya gränssnitt, UnitEnum (när det gäller rena nummer) och BackedEnum (för nummer med säkerhetskopierade värden). Dessa kan användas i generisk ramkod som fungerar med valfritt nummer. Gränssnitten kan inte implementeras manuellt med userland -kod.

Enums kommer att landa i PHP som en del av 8.1 -versionen i november 2021. De är redan tillgängliga i de senaste betaversionerna. PHP 8.1 levererar också flera andra bekvämlighetsfunktioner, inklusive skrivskyddade egenskaper och skärningstyper.