Skip to content

枚举值清单

概述

枚举提供了获取所有 case 的内置支持,使得开发者可以轻松遍历所有枚举值。UnitEnum::cases() 方法返回包含所有枚举 case 实例的数组,结合 namevalue 属性,可以实现枚举的遍历、计数、列表生成等操作。

版本要求

cases() 方法是 PHP 8.1+ 枚举内置方法。

基础概念

获取枚举值的方式

方式说明返回类型
Enum::cases()获取所有 case 实例array<int, static>
$enum->name获取 case 名称string
$enum->value获取 case 标量值(仅 Backed Enum)int|string

语法与代码

cases() 获取所有枚举值

php
<?php

declare(strict_types=1);

enum Suit
{
    case Hearts;
    case Diamonds;
    case Clubs;
    case Spades;
}

// 获取所有 case
$allSuits = Suit::cases();
// [Suit::Hearts, Suit::Diamonds, Suit::Clubs, Suit::Spades]

foreach ($allSuits as $suit) {
    echo $suit->name . PHP_EOL;
}
// Hearts
// Diamonds
// Clubs
// Spades

遍历枚举

php
<?php

declare(strict_types=1);

enum Season
{
    case Spring;
    case Summer;
    case Autumn;
    case Winter;

    public function emoji(): string
    {
        return match ($this) {
            self::Spring => '🌸',
            self::Summer => '☀️',
            self::Autumn => '🍂',
            self::Winter => '❄️',
        };
    }
}

foreach (Season::cases() as $season) {
    echo "{$season->emoji()} {$season->name}" . PHP_EOL;
}

count() 计数

php
<?php

declare(strict_types=1);

enum Color
{
    case Red;
    case Green;
    case Blue;

    public static function count(): int
    {
        return count(self::cases());
    }
}

echo Color::count();  // 3

names() 静态方法 — 获取所有名称

php
<?php

declare(strict_types=1);

enum Role: string
{
    case Admin = 'admin';
    case Editor = 'editor';
    case Viewer = 'viewer';

    /**
     * 获取所有 case 名称
     * @return string[]
     */
    public static function names(): array
    {
        return array_map(fn(self $case) => $case->name, self::cases());
    }
}

print_r(Role::names());
// ['Admin', 'Editor', 'Viewer']

values() 静态方法 — 获取所有值

php
<?php

declare(strict_types=1);

enum Priority: int
{
    case Low = 1;
    case Medium = 2;
    case High = 3;
    case Critical = 4;

    /**
     * 获取所有 case 值
     * @return int[]
     */
    public static function values(): array
    {
        return array_map(fn(self $case) => $case->value, self::cases());
    }
}

print_r(Priority::values());
// [1, 2, 3, 4]

构建键值对映射

php
<?php

declare(strict_types=1);

enum OrderStatus: string
{
    case Pending = 'pending';
    case Processing = 'processing';
    case Shipped = 'shipped';
    case Delivered = 'delivered';
    case Cancelled = 'cancelled';

    /**
     * 值到名称的映射
     */
    public static function valueNameMap(): array
    {
        $map = [];
        foreach (self::cases() as $case) {
            $map[$case->value] = $case->name;
        }
        return $map;
    }

    /**
     * 名称到实例的映射
     */
    public static function nameInstanceMap(): array
    {
        $map = [];
        foreach (self::cases() as $case) {
            $map[$case->name] = $case;
        }
        return $map;
    }
}

$map = OrderStatus::valueNameMap();
// ['pending' => 'Pending', 'processing' => 'Processing', ...]

详细说明

cases() 的返回类型

cases() 返回的是一个索引数组,数组的键是从 0 开始的整数索引,值是枚举 case 实例:

php
<?php

declare(strict_types=1);

enum Fruit
{
    case Apple;
    case Banana;
    case Cherry;
}

$cases = Fruit::cases();
var_dump(array_keys($cases));   // [0, 1, 2]
var_dump(get_class($cases[0])); // "Fruit"
var_dump($cases[0]->name);      // "Apple"

过滤枚举值

php
<?php

declare(strict_types=1);

enum Plan: string
{
    case Free = 'free';
    case Basic = 'basic';
    case Premium = 'premium';

    public function isPaid(): bool
    {
        return $this !== self::Free;
    }

    /**
     * 获取所有付费计划
     */
    public static function paidPlans(): array
    {
        return array_filter(
            self::cases(),
            fn(self $case) => $case->isPaid()
        );
    }

    /**
     * 获取所有免费计划
     */
    public static function freePlans(): array
    {
        return array_filter(
            self::cases(),
            fn(self $case) => !$case->isPaid()
        );
    }
}

$paid = Plan::paidPlans();    // [Plan::Basic, Plan::Premium]
$free = Plan::freePlans();    // [Plan::Free]

搜索枚举值

php
<?php

declare(strict_types=1);

enum HttpStatus: int
{
    case Ok = 200;
    case Created = 201;
    case BadRequest = 400;
    case NotFound = 404;
    case ServerError = 500;

    /**
     * 根据名称查找
     */
    public static function findByName(string $name): ?self
    {
        foreach (self::cases() as $case) {
            if ($case->name === $name) {
                return $case;
            }
        }
        return null;
    }

    /**
     * 根据条件查找
     */
    public static function findBy(callable $callback): ?self
    {
        foreach (self::cases() as $case) {
            if ($callback($case)) {
                return $case;
            }
        }
        return null;
    }
}

// 通过名称查找
$status = HttpStatus::findByName('NotFound');
echo $status?->value;  // 404

// 通过条件查找
$status = HttpStatus::findBy(fn($s) => $s->value >= 400 && $s->value < 500);

实战示例

场景一:表单下拉选项

php
<?php

declare(strict_types=1);

enum Category: string
{
    case Technology = 'tech';
    case Business = 'business';
    case Health = 'health';
    case Education = 'education';
    case Entertainment = 'entertainment';

    public function label(): string
    {
        return match ($this) {
            self::Technology => '科技',
            self::Business => '商业',
            self::Health => '健康',
            self::Education => '教育',
            self::Entertainment => '娱乐',
        };
    }

    /**
     * 生成 HTML select 选项
     */
    public static function toSelectOptions(?self $selected = null): string
    {
        $options = '';
        foreach (self::cases() as $case) {
            $selectedAttr = $case === $selected ? ' selected' : '';
            $options .= sprintf(
                '<option value="%s"%s>%s</option>',
                $case->value,
                $selectedAttr,
                $case->label()
            );
        }
        return $options;
    }
}

echo '<select name="category">';
echo Category::toSelectOptions(Category::Technology);
echo '</select>';

场景二:枚举验证

php
<?php

declare(strict_types=1);

enum Currency: string
{
    case Cny = 'CNY';
    case Usd = 'USD';
    case Eur = 'EUR';
    case Gbp = 'GBP';
    case Jpy = 'JPY';

    /**
     * 检查值是否是合法的枚举值
     */
    public static function isValid(string $value): bool
    {
        return in_array($value, self::values(), true);
    }

    /**
     * 获取所有值
     */
    public static function values(): array
    {
        return array_map(fn(self $c) => $c->value, self::cases());
    }

    /**
     * 验证并返回枚举
     */
    public static function validateOrFail(string $value): self
    {
        return self::tryFrom($value)
            ?? throw new \InvalidArgumentException("Invalid currency: {$value}");
    }
}

// 验证
var_dump(Currency::isValid('CNY'));   // true
var_dump(Currency::isValid('XYZ'));   // false
$currency = Currency::validateOrFail('USD');

注意事项

注意事项

  • cases() 返回的数组顺序与枚举 case 的声明顺序一致
  • cases() 返回的是索引数组,键名从 0 开始
  • 纯枚举没有 value 属性,调用会报错
  • 枚举 case 数量在运行时是固定的,不会改变

小贴士

  • 使用 cases() 生成表单选项、配置列表等
  • 将常用的枚举操作(如 values、names)封装为静态方法
  • 对于大型枚举(超过 10 个 case),考虑使用 array_column 等函数简化操作

最佳实践

1. 为枚举提供便捷的静态方法

php
<?php

declare(strict_types=1);

enum Status: string
{
    case Active = 'active';
    case Inactive = 'inactive';

    public static function values(): array
    {
        return array_column(self::cases(), 'value');
    }

    public static function names(): array
    {
        return array_column(self::cases(), 'name');
    }
}

2. 使用 array_column 简化操作

php
<?php

declare(strict_types=1);

enum Tag: string
{
    case Important = 'important';
    case Urgent = 'urgent';
    case Optional = 'optional';

    // 使用 array_column 提取 name 或 value
    public static function allNames(): array
    {
        return array_column(self::cases(), 'name');
    }

    public static function allValues(): array
    {
        return array_column(self::cases(), 'value');
    }
}

参考链接