本文系翻譯,原文地址:https://stitcher.io/blog/php-enums
PHP 8.1:枚舉
它們終于來了——PHP 8.1中將添加對枚舉的內(nèi)置支持!有些人可能認(rèn)為他們早就應(yīng)該這樣做了,但你沒有聽到我的抱怨;我很高興他們做到了!這篇文章致力于深入研究新添加的功能。
像往常一樣,在我的 PHP 功能帖子中,我們首先對枚舉的外觀進(jìn)行高級概述:
enum Status { case DRAFT; case PUBLISHED; case ARCHIVED; }
枚舉的好處是它們代表了一組常量值,但最重要的是這些值可以被鍵入,如下所示:
class BlogPost { public function __construct( public Status $status, ) {} }
在這個例子中,創(chuàng)建一個枚舉并將其傳遞給 aBlogPost看起來像這樣:
$post = new BlogPost(Status::DRAFT);
這就是基礎(chǔ)知識,正如您所看到的,它們一點也不復(fù)雜。雖然有很多旁注需要做,讓我們深入看看枚舉!
#枚舉方法
枚舉可以定義方法,就像類一樣。這是一個非常強(qiáng)大的功能,尤其是與match運算符結(jié)合使用時:
enum Status { case DRAFT; case PUBLISHED; case ARCHIVED; public function color(): string { return match($this) { Status::DRAFT => 'grey', Status::PUBLISHED => 'green', Status::ARCHIVED => 'red', }; } }
方法可以像這樣使用:
$status = Status::ARCHIVED; $status->color(); // 'red'
靜態(tài)方法也是允許的:
enum Status { // … public static function make(): Status { // … } }
您還可以self在枚舉中使用:
enum Status { // … public function color(): string { return match($this) { self::DRAFT => 'grey', self::PUBLISHED => 'green', self::ARCHIVED => 'red', }; } }
#枚舉接口
枚舉可以實現(xiàn)接口,就像普通類一樣:
interface HasColor { public function color(): string; } enum Status implements HasColor { case DRAFT; case PUBLISHED; case ARCHIVED; public function color(): string { /* … */ } }
#枚舉值——又名“支持枚舉”
枚舉值在內(nèi)部由對象表示,但您可以根據(jù)需要為它們賦值;這對于例如很有用。將它們序列化到數(shù)據(jù)庫中。
enum Status: string { case DRAFT = 'draft'; case PUBLISHED = 'published'; case ARCHIVED = 'archived'; }
注意枚舉定義中的類型聲明。它表示所有枚舉值都屬于給定類型。您也可以將其設(shè)為int. 請注意, onlyint和string允許作為枚舉值。
enum Status: int { case DRAFT = 1; case PUBLISHED = 2; case ARCHIVED = 3; }
類型枚舉的技術(shù)術(shù)語稱為“支持枚舉”,因為它們由更簡單的值“支持”。如果您決定分配枚舉值,則所有案例都應(yīng)該有一個值。你不能混合和匹配它們。沒有“支持”的枚舉被稱為“純枚舉”。
#帶接口的支持枚舉
如果您將支持的枚舉和接口結(jié)合使用,則枚舉類型必須直接位于枚舉名稱之后,implements關(guān)鍵字之前。
enum Status: string implements HasColor { case DRAFT = 'draft'; case PUBLISHED = 'published'; case ARCHIVED = 'archived'; // … }
#序列化支持的枚舉
如果您要為枚舉案例分配值,您可能需要一種方法來序列化和反序列化它們。序列化它們意味著您需要一種訪問枚舉值的方法。這是通過只讀公共屬性完成的:
$value = Status::PUBLISHED->value; // 2
可以使用以下方法從值中恢復(fù)枚舉:Enum::from
$status = Status::from(2); // Status::PUBLISHED
如果傳遞了未知值tryFrom,還有一個返回null。如果你會使用from會有一個例外。
$status = Status::from('unknown'); // ValueError $status = Status::tryFrom('unknown'); // null
請注意,您還可以在枚舉上使用內(nèi)置函數(shù)serialize和unserialize函數(shù)。此外,您可以json_encode與支持的枚舉結(jié)合使用,其結(jié)果將是枚舉值??梢酝ㄟ^實現(xiàn)來覆蓋此行為JsonSerializable。
#列出枚舉值
您可以使用靜態(tài)方法獲取枚舉中所有可用案例的列表:Enum::cases()
Status::cases(); /* [ Status::DRAFT, Status::PUBLISHED, Status::ARCHIVED ] */
請注意,此數(shù)組包含實際的枚舉對象:
array_map( fn(Status $status) => $status->color(), Status::cases() );
#枚舉是對象
我已經(jīng)提到枚舉值表示為對象,實際上它們是單例對象。這意味著您可以像這樣與它們進(jìn)行比較:
$statusA = Status::PENDING; $statusB = Status::PENDING; $statusC = Status::ARCHIVED; $statusA === $statusB; // true $statusA === $statusC; // false $statusC instanceof Status; // true
#枚舉作為數(shù)組鍵
由于枚舉值實際上是對象,因此目前無法將它們用作數(shù)組鍵。以下將導(dǎo)致錯誤:
$list = [ Status::DRAFT => 'draft', // … ];
有一個 RFC來改變這種行為,但它還沒有被投票。
這意味著您只能使用枚舉作為SplObjectStorage和 中的鍵WeakMaps。
#性狀
枚舉可以像類一樣使用特征,但有