ZetCode

PHP 枚举

最后修改于 2025 年 4 月 16 日

PHP enum 关键字引入了枚举,这是一种特殊的类。枚举表示一组固定的可能值,使代码更具可读性和类型安全性。它们是在 PHP 8.1 中添加的。

基本定义

一个 enum 定义了一个自定义类型,其可能值的集合是有限的。每个可能的值被称为 "case"。枚举可以拥有方法并像常规类一样实现接口。

有两种类型的枚举:纯枚举(没有值)和带值枚举(带有标量值)。带值枚举必须声明其值类型(int 或 string)。

语法:enum EnumName { case Case1; case Case2; } 用于纯枚举。对于带值枚举:enum EnumName: type { case Case1 = value; }

基本枚举声明

此示例演示了一个简单的纯枚举,它代表 HTTP 方法。

basic_enum.php
<?php

declare(strict_types=1);

enum HttpMethod {
    case GET;
    case POST;
    case PUT;
    case DELETE;
}

$method = HttpMethod::POST;

if ($method === HttpMethod::POST) {
    echo "This is a POST request.";
}

该代码定义了一个枚举,其中包含四个 HTTP 方法 case。我们创建一个枚举变量并将其与一个 case 进行比较。枚举提供了优于使用字符串或整数的类型安全。每个 case 都是枚举类型的一个实例。

带值枚举

此示例显示了一个带值枚举,其中包含状态码的字符串值。

backed_enum.php
<?php

declare(strict_types=1);

enum Status: string {
    case PENDING = 'pending';
    case APPROVED = 'approved';
    case REJECTED = 'rejected';
}

$status = Status::APPROVED;

echo "Status: " . $status->value;

枚举为每个 case 声明字符串值。我们使用 value 属性访问该值。带值枚举必须声明所有带有值的 case。值在枚举中必须是唯一的。

枚举方法

此示例演示了向枚举添加方法。

enum_methods.php
<?php

declare(strict_types=1);

enum Direction {
    case NORTH;
    case SOUTH;
    case EAST;
    case WEST;
    
    public function opposite(): self {
        return match($this) {
            self::NORTH => self::SOUTH,
            self::SOUTH => self::NORTH,
            self::EAST => self::WEST,
            self::WEST => self::EAST,
        };
    }
}

$dir = Direction::NORTH;
$opposite = $dir->opposite();

echo "Opposite of NORTH is " . $opposite->name;

枚举定义了一个 opposite 方法,该方法返回另一个枚举 case。我们使用模式匹配与 match 来确定相反的方向。方法可以通过 $this 访问当前 case。

枚举实现接口

此示例显示了一个实现接口的枚举。

enum_interface.php
<?php

declare(strict_types=1);

interface Colorful {
    public function color(): string;
}

enum Suit: string implements Colorful {
    case HEARTS = 'H';
    case DIAMONDS = 'D';
    case CLUBS = 'C';
    case SPADES = 'S';
    
    public function color(): string {
        return match($this) {
            self::HEARTS, self::DIAMONDS => 'Red',
            self::CLUBS, self::SPADES => 'Black',
        };
    }
}

$card = Suit::DIAMONDS;
echo "Card color: " . $card->color();

枚举实现了 Colorful 接口,其中包含一个 color 方法。每个 case 必须实现接口方法。这允许枚举参与类型层次结构。该方法根据花色返回不同的颜色。

枚举在 Switch 语句中

此示例演示了在 switch 语句中使用枚举。

enum_switch.php
<?php

declare(strict_types=1);

enum UserRole {
    case ADMIN;
    case EDITOR;
    case SUBSCRIBER;
    case GUEST;
}

function getPermissions(UserRole $role): string {
    switch ($role) {
        case UserRole::ADMIN:
            return "All permissions";
        case UserRole::EDITOR:
            return "Edit content";
        case UserRole::SUBSCRIBER:
            return "View premium content";
        default:
            return "Basic viewing";
    }
}

echo getPermissions(UserRole::EDITOR);

该函数接受一个枚举参数,并根据其值进行切换。每个 case 处理不同的枚举值。默认 case 处理任何未指定的值。枚举与 switch 语句自然配合使用以进行控制流。

枚举静态方法

此示例显示了枚举中的静态方法,用于创建和验证。

enum_static.php
<?php

declare(strict_types=1);

enum Size: int {
    case SMALL = 1;
    case MEDIUM = 2;
    case LARGE = 3;
    
    public static function fromValue(int $value): self {
        return match($value) {
            1 => self::SMALL,
            2 => self::MEDIUM,
            3 => self::LARGE,
            default => throw new ValueError("Invalid size value"),
        };
    }
    
    public static function isValid(int $value): bool {
        return $value >= 1 && $value <= 3;
    }
}

$size = Size::fromValue(2);
echo "Size: " . $size->name;

echo "Is 4 valid? " . (Size::isValid(4) ? 'Yes' : 'No');

枚举提供了静态方法,用于从值创建实例和验证值。fromValue 为无效值抛出异常。静态方法在枚举类本身而不是实例上调用。

带有属性的枚举

此示例演示了将 PHP 属性与枚举 case 一起使用。

enum_attributes.php
<?php

declare(strict_types=1);

#[Attribute]
class Description {
    public function __construct(public string $text) {}
}

enum LogLevel {
    #[Description("Debug-level messages")]
    case DEBUG;
    
    #[Description("Informational messages")]
    case INFO;
    
    #[Description("Warning conditions")]
    case WARNING;
    
    #[Description("Error conditions")]
    case ERROR;
}

$reflection = new ReflectionEnum(LogLevel::class);
$case = $reflection->getCase('DEBUG');
$attrs = $case->getAttributes(Description::class);

foreach ($attrs as $attr) {
    echo $attr->newInstance()->text;
}

该代码定义了一个自定义属性并将其应用于枚举 case。我们使用反射在运行时读取属性值。属性提供有关枚举 case 的元数据。此模式对于文档或框架集成非常有用。

最佳实践

来源

PHP 枚举文档

本教程涵盖了 PHP 枚举,并提供了实际示例,展示了枚举声明、方法、接口和高级功能。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出 所有 PHP 教程