Si të përdorni Enums në PHP 8.1


PHP 8.1 më në fund do të shtojë mbështetje gjuhësore për enums. Enums, shkurt për enumerations, janë lloje që mund të instantohen vetëm me vlera specifike. Ato zakonisht gjenden në gjuhë të tjera të orientuara nga objekti, por më parë kanë kërkuar zgjidhje për tokën e përdoruesit për t'u zbatuar në PHP.

Sintaksa bazë

Ja se si duket një numër i thjeshtë:

enum PostStatus {
    case Published;
    case InReview;
    case Draft;
}

Fjala kyçe case, më parë pjesë e deklaratave switch, përdoret për të përcaktuar vlerat specifike që pranon enum. Vlerat referohen në të njëjtën mënyrë si konstantet e klasës:

$published = PostStatus::Published;

Enum-et sillen në mënyrë të ngjashme me klasat dhe ndërfaqet. Ato janë plotësisht të pajtueshme me sistemin e tipit, kështu që ju mund të shkruani që një funksion pranon vetëm një vlerë të përcaktuar në një numër:

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

Këtu është një shembull i përdorimit të klasës BlogPost:

// OK
$post = new BlogPost(
    "Example Post",
    "An example",
    PostStatus::Draft
);
 
// TypeError: Argument #3 ($Status) must be of type PostStatus
$post = new BlogPost(
    "Broken Example",
    "A broken example",
    "Submitted"
);

Shkalla e parë funksionon sepse $Status e saj është një vlerë e vlefshme nga numri PostStatus. Në rastin e dytë, një varg i thjeshtë kalohet si $Status, i cili është i ndaluar pasi vlera duhet të përcaktohet brenda PostStatus.

Rastet Enum përfaqësohen si konstante në objektin enum. Kjo do të thotë që ju mund t'i përdorni ato si vlera statike dhe si pjesë e shprehjeve konstante. Konstruktori BlogPost tregon një rast enum që përdoret si një vlerë parametri të paracaktuar, ku $Status vendoset automatikisht në Draft kur telefonuesi nuk jep asnjë vlerë.

Ju mund të përdorni të gjitha vlerat e disponueshme në një numër duke përdorur metodën e tij rastet:

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

Njerëz të pastër vs të mbështetur

Numri PostStatus më sipër është një numër i pastër. Ai përmban vetëm deklarata rast, pa të dhëna shtesë. PHP gjithashtu ju lejon t'i bashkëngjitni një vlerë rasteve enum, duke krijuar një numër të mbështetur.

enum PostStatus : string {
    case Published = "S1";
    case InReview = "S2";
    case Draft = "S3";
}

Këtu, numri PostStatus është modifikuar për të krijuar një numër të mbështetur. Shkrimi i shkrimit në përkufizimin e enum përcakton që çdo rast ka një vlerë vargu të caktuar për të. Në këtë shembull, ne po supozojmë se çdo status postimi i emërtuar ka një identifikues të shkurtër të lidhur. Mund të jetë ky identifikues që ruhet në bazën e të dhënave kur postimet vazhdojnë.

Ju mund të përdorni vlerat e mbështetura nëpërmjet veçorisë value në rastet e rasteve:

class BlogPostRepository {
 
    public function save(BlogPost $Post) : void {
        $this -> insert(
            "blog_posts",
            [
                "headline" => $Post -> Headline,
                "content" => $Post -> Content,
                "status" => $Post -> Status -> value
            ]
        );
    }
 
}
 
$post = new BlogPost("Example", "Demo", PostStatus::Published);
(new BlogPostRepository()) -> save($post);

Ky shembull do të vendoste vlerën e fushës së vazhdueshme statusS1, bazuar në versionin e mbështetur të enumit PostStatus të paraqitur më sipër.

Numrat e mbështetur vetëm pranojnë vargjet dhe numrat e plotë si vlera. Nuk është e mundur të përdoret as lloji i bashkimit string|int. Përveç kësaj, çdo rast ka nevojë për një vlerë unike - shembulli i mëposhtëm nuk është i lejueshëm:

enum PostStatus : string {
 
    case Published = "S1";
    case Draft = "S1";
 
}

PHP ofron një metodë të dobishme në enums për të krijuar një shembull nga një vlerë e mbështetur:

// fetch the blog post from earlier from the database
// the "status" field = S1
$status = PostStatus::from($record["status"]);

Metoda from() do të hidraton instancat nga rastet e vlerave. Në këtë shembull, S1 është rikthyer në rastin Publikuar dhe kodi juaj merr një shembull të PostStatus::Published.

from() hedh një ValueError nëse vlera e hyrjes është e pavlefshme; në skenarët ku e dini se vlera mund të mos jetë e përdorshme, në vend të kësaj mund të përdoret metoda alternative tryFrom(). Kjo kthen null kur nuk ka përputhje, në vend që të hedhë gabimin.

Shtimi i metodave në Enums

Duke qenë se numrat bazohen në klasa, mund t'u shtoni edhe metoda!

enum PostStatus {
 
    case Published;
    case Draft;
 
    public function isPubliclyAccessible() : bool {
        return ($this instanceof self::Published);
    }
 
}

Kjo ju lejon të mbani sjelljen specifike të rastit brenda numrit tuaj, në vend që ta dyfishoni atë në bazën tuaj të kodit.

Enums gjithashtu mund të implementojnë ndërfaqe:

enum PostStatus implements PublicAccessGatable {
 
    case Published;
    case Draft;
 
    public function isPubliclyAccessible() : bool {
        return ($this instanceof self::Published);
    }
 
}

Tani mund të kaloni një shembull PostStatus çdo gjëje që pranon një PublicAccessGatable:

class UserAuthenticator {
 
    function shouldAllowAccess(PublicAccessGatable $Resource) : bool {
        return ($this -> User -> isAdmin() || $Resource -> isPubliclyAccessible());
    }
 
}
 
$auth = new UserAuthenticator();
 
// get a blog post from the database
if (!$auth -> shouldAllowAccess($post -> Status)) {
    http_response_code(403);
}

Nuk ka kufizime për atë që mund të bëni me metodat enum – ato janë metoda të rregullta PHP, në fund të fundit – por në përgjithësi do të prisni që ata të kryejnë një lloj krahasimi kundër rastit të shembullit, pastaj të kthejnë një vlerë statike. Enums mund të përdorin tipare, kështu që ju mund të tërhiqni metodat ekzistuese të cilat i keni abstraguar gjithashtu në këtë mënyrë.

Ju mund të përdorni metodat publike, të mbrojtura dhe private në enume, megjithëse të mbrojtura dhe private kanë të njëjtin efekt. Numrat nuk mund të zgjerojnë njëri-tjetrin, kështu që private është efektivisht i tepërt. Ju nuk mund të shtoni as një konstruktor apo destruktor. Metodat statike mbështeten dhe mund të thirren në klasën enum ose në rastet e saj.

Konstante

Enumet mund të kenë gjithashtu konstantet e tyre, qoftë si vlera të rregullta letrare ose si referencë për një rast enum:

enum PostStatus {
 
    case Published;
    case Draft;
 
    public const Live = self::Published;
    public const PlainConstant = "foobar";
 
}

Kjo ka potencialin për të krijuar konfuzion pasi e njëjta sintaksë përdoret për të hyrë në rastet (enum instancat) dhe konstantet:

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

Vetëm $publikuar do të plotësonte një shtypje PostStatus, pasi $plain i referohet një vlere të thjeshtë skalare.

Kur të përdorni Enums?

Numrat janë për rastet kur keni nevojë për fleksibilitet në vlerën që mund të marrë një variabël, por vetëm midis një grupi të paracaktuar rastesh të mundshme.

Klasa e postimeve në blog që kryhet përmes këtij postimi është një shembull klasik. Postimet mund të jenë vetëm në një nga një grup shtetesh të njohura, por PHP më parë nuk kishte asnjë mënyrë të drejtpërdrejtë për ta arritur këtë.

Në versionet e vjetra, mund të keni përdorur këtë qasje:

class PostStatus {
    const Published = 0;
    const Draft = 1;
}
 
class BlogPost {
    public function __construct(
        public string $Headline,
        public int $Status
    ) {}
}
 
$post = new BlogPost("My Headline", PostStatus::Published);

Problemi këtu është se $Status në fakt pranon çdo numër të plotë, kështu që thirrja e mëposhtme do të ishte plotësisht e vlefshme:

$post = new BlogPost("My Headline", 9000);

Për më tepër, BlogPost dhe PostStatus janë shkëputur plotësisht – nuk ka asnjë mënyrë që dikush që lexon BlogPost të mund të mësojë gamën e vlerave që $Status në fakt pranon. Ndërsa këto çështje mund të zbuten duke përdorur tiparet e duhura të tipit docblock, ose paketa fake enum të palëve të treta, të gjitha ato po shtojnë shtresa shtesë rreth një koncepti që gjuhët e tjera të programimit e bëjnë të thjeshtë.

Shtimi i numrave vendas në PHP është një hap që ndihmon për të rrumbullakosur sistemin e tipit të gjuhës. Më në fund mund të shtypni vlerat e lejuara në një mënyrë që t'i mbajë të gjithë në të njëjtën faqe. Nëse kaloni një vlerë të pavlefshme, do të merrni një gabim në kohën e ekzekutimit. IDE-ja juaj mund t'ju ndihmojë më mirë në ofrimin e vlerave të sakta, pasi do të dijë se $Status pranon vetëm tre opsione, në vend të çdo numër të plotë.

konkluzioni

Enums adresojnë disa pika të zakonshme të dhimbjes së zhvilluesit kur punoni në PHP. Ato bëjnë të mundur shkrimin e shkrimit që parametrat, vlerat e kthyera dhe vetitë duhet të jenë një nga një grup opsionesh të paracaktuara.

Enumet janë entitete fleksibël të bazës së kodit, të cilat mund t'i mbani të thjeshta në formë të pastër, ose t'i zgjeroni me vlera të mbështetura, zbatime të ndërfaqes dhe metoda të personalizuara. Enumet sillen në mënyrë të ngjashme me objektet e rregullta në shumicën e rasteve dhe mbështesin veçoritë e klasës si __call(), __invoke dhe ::class.

Ju mund t'i shqyrtoni enumet me funksionin e ri enum_exists() dhe klasën e Reflection ReflectionEnum. Për më tepër, enums implementojnë dy ndërfaqe të reja, UnitEnum (në rastin e enum-ve të pastra) dhe BackedEnum (për numrat me vlera të mbështetura). Këto mund të përdoren në kodin e përgjithshëm të kornizës që funksionon me çdo numër. Ndërfaqet nuk mund të zbatohen manualisht nga kodi i tokës së përdoruesit.

Enums do të futet në PHP si pjesë e lëshimit 8.1 në nëntor 2021. Ata janë tashmë të disponueshëm në versionet më të fundit beta. PHP 8.1 do të dërgojë gjithashtu disa veçori të tjera komoditeti, duke përfshirë vetitë vetëm për lexim dhe llojet e kryqëzimeve.


Të gjitha të drejtat e rezervuara. © Linux-Console.net • 2019-2024