PHP 列舉 (Enums)

Enum(列舉)是 PHP 8.1 引入的一種特殊型別,用來定義一組固定的具名值。它比傳統的 const 常數更安全、更有表現力,且支援型別檢查。

基本列舉 (Pure Enums)

最簡單的列舉只包含名稱。

<?php
enum Status {
    case Pending;
    case Active;
    case Completed;
    case Archived;
}

function processStatus(Status $status) {
    if ($status === Status::Active) {
        // 處理活動中的狀態
    }
}

processStatus(Status::Pending); // OK
// processStatus('Pending');   // TypeError: 必須是 Status 實例
?>

帶值列舉 (Backed Enums)

如果你需要將列舉與特定的值(如資料庫中的字串或整數)關聯,可以使用帶值列舉。帶值列舉必須指定型別(僅限 intstring)。

<?php
enum OrderStatus: string {
    case Pending = 'P';
    case Shipping = 'S';
    case Delivered = 'D';
}

// 取得關聯的值
echo OrderStatus::Pending->value; // 輸出:P

// 從值建立列舉執行實例
$status = OrderStatus::from('S'); // 得到 OrderStatus::Shipping
$status = OrderStatus::tryFrom('X'); // 找不到時回傳 null

echo $status?->name; // 輸出:Shipping (名稱)
?>

列舉的方法

列舉可以包含方法,這讓它們比簡單的常數強大得多。

<?php
enum UserRole {
    case Admin;
    case Editor;
    case Viewer;

    public function getLabel(): string {
        return match($this) {
            self::Admin => '管理員',
            self::Editor => '編輯者',
            self::Viewer => '檢視者',
        };
    }

    public function canEdit(): bool {
        return $this === self::Admin || $this === self::Editor;
    }
}

$role = UserRole::Admin;
echo $role->getLabel(); // 輸出:管理員
var_dump($role->canEdit()); // bool(true)
?>

列舉實作介面

列舉也可以實作介面。

<?php
interface HasLabel {
    public function label(): string;
}

enum Priority implements HasLabel {
    case Low;
    case High;

    public function label(): string {
        return match($this) {
            self::Low => '低優先度',
            self::High => '高優先度',
        };
    }
}
?>

列舉常數

列舉內也可以定義常數。

<?php
enum Size {
    case Small;
    case Large;

    public const DEFAULT = self::Small;
}

$size = Size::DEFAULT;
?>

取得所有列舉項

你可以使用 cases() 方法取得列舉中定義的所有項目陣列。

<?php
foreach (OrderStatus::cases() as $status) {
    echo $status->name . " => " . $status->value . "\n";
}
?>

Enum vs Const

特性常數 (const)列舉 (Enum)
型別安全弱,只是基本型別強,擁有獨立型別
自動完成一般非常好
內建方法有 (value, name, cases)
自訂邏輯可定義方法與實作介面
PHP 版本全部PHP 8.1+

什麼時候該用 Enum?

  • 當有一組固定且已知的正體選項時(如:性別、訂單狀態、權限等級)。
  • 當你需要確保傳入的參數絕對是該組選項之一時。
  • 當你需要為這些選項添加額外邏輯(方法)時。