PHP 8.1 枚举(Enums)详解

目录

  1. 什么是枚举?
  2. 基本语法
  3. 纯值枚举
  4. 回退枚举
  5. 枚举方法
  6. 接口实现
  7. 实用示例
  8. 注意事项

什么是枚举?

枚举是一种特殊的数据类型,允许定义一组命名的常量值。在 PHP 8.1 之前,开发者通常使用类常量或数组来模拟枚举,但 PHP 8.1 引入了原生枚举支持,提供了更好的类型安全性和功能。

基本语法

php 复制代码
// 定义纯值枚举
enum Status: string {
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
}

// 使用枚举
$status = Status::DRAFT;

// 获取枚举值
echo $status->value; // 输出: draft

// 通过值获取枚举实例
$status = Status::from('draft');
// 或者安全获取(失败时返回 null)
$status = Status::tryFrom('draft');

纯值枚举(Pure Enums)

php 复制代码
// 整数类型的枚举
enum Priority: int {
    case LOW = 1;
    case MEDIUM = 2;
    case HIGH = 3;
    case CRITICAL = 4;
}

// 字符串类型的枚举
enum Color: string {
    case RED = '#FF0000';
    case GREEN = '#00FF00';
    case BLUE = '#0000FF';
}

// 使用示例
$priority = Priority::HIGH;
echo $priority->value; // 输出: 3
echo $priority->name;  // 输出: HIGH

// 类型提示
function setPriority(Priority $priority): void {
    echo "Setting priority to: {$priority->value}\n";
}

setPriority(Priority::CRITICAL);

回退枚举(Backed Enums)

php 复制代码
// 回退枚举可以具有标量值(int 或 string)
enum HttpStatus: int {
    case OK = 200;
    case CREATED = 201;
    case BAD_REQUEST = 400;
    case NOT_FOUND = 404;
    case SERVER_ERROR = 500;
}

// 实用方法
$status = HttpStatus::from(404);
echo $status->name;  // NOT_FOUND
echo $status->value; // 404

// 遍历所有枚举值
foreach (HttpStatus::cases() as $case) {
    echo "{$case->name} = {$case->value}\n";
}

枚举方法

枚举可以包含方法和静态方法:

php 复制代码
enum Suit: string {
    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',
        };
    }
    
    // 静态方法
    public static function random(): self {
        $cases = self::cases();
        return $cases[array_rand($cases)];
    }
}

// 使用示例
$suit = Suit::HEARTS;
echo $suit->color(); // 输出: red

$randomSuit = Suit::random();
echo $randomSuit->value;

接口实现

枚举可以实现接口:

php 复制代码
interface Describable {
    public function description(): string;
}

enum UserRole: string implements Describable {
    case ADMIN = 'admin';
    case EDITOR = 'editor';
    case VIEWER = 'viewer';
    
    public function description(): string {
        return match($this) {
            self::ADMIN => '具有完全访问权限',
            self::EDITOR => '可以创建和编辑内容',
            self::VIEWER => '只能查看内容',
        };
    }
}

// 使用示例
$role = UserRole::ADMIN;
echo $role->description(); // 输出: 具有完全访问权限

实用示例

示例 1:订单状态管理

php 复制代码
enum OrderStatus: string {
    case PENDING = 'pending';
    case PROCESSING = 'processing';
    case SHIPPED = 'shipped';
    case DELIVERED = 'delivered';
    case CANCELLED = 'cancelled';
    
    public function isCompleted(): bool {
        return in_array($this, [self::DELIVERED, self::CANCELLED]);
    }
    
    public function canTransitionTo(self $status): bool {
        return match($this) {
            self::PENDING => in_array($status, [self::PROCESSING, self::CANCELLED]),
            self::PROCESSING => in_array($status, [self::SHIPPED, self::CANCELLED]),
            self::SHIPPED => $status === self::DELIVERED,
            default => false,
        };
    }
}

// 使用
$status = OrderStatus::PENDING;
if ($status->canTransitionTo(OrderStatus::PROCESSING)) {
    echo "可以转换到处理状态\n";
}

示例 2:权限系统

php 复制代码
enum Permission: int {
    case READ = 1;      // 0001
    case WRITE = 2;     // 0010
    case DELETE = 4;    // 0100
    case ADMIN = 7;     // 0111 (READ|WRITE|DELETE)
    
    public function hasPermission(self $permission): bool {
        return ($this->value & $permission->value) === $permission->value;
    }
    
    public function addPermission(self $permission): self {
        return self::from($this->value | $permission->value);
    }
}

// 使用
$userPerm = Permission::READ->addPermission(Permission::WRITE);
echo $userPerm->hasPermission(Permission::WRITE) ? '有写权限' : '无写权限';

示例 3:配置管理

php 复制代码
enum Environment: string {
    case LOCAL = 'local';
    case STAGING = 'staging';
    case PRODUCTION = 'production';
    
    public function config(): array {
        return match($this) {
            self::LOCAL => [
                'debug' => true,
                'cache' => false,
                'db_host' => 'localhost',
            ],
            self::STAGING => [
                'debug' => true,
                'cache' => true,
                'db_host' => 'staging.db.example.com',
            ],
            self::PRODUCTION => [
                'debug' => false,
                'cache' => true,
                'db_host' => 'production.db.example.com',
            ],
        };
    }
}

// 使用
$env = Environment::from($_ENV['APP_ENV'] ?? 'local');
$config = $env->config();

注意事项

  1. 枚举是单例的:每个枚举值都是单例实例
  2. 不可序列化 :枚举不能直接序列化,但可以通过 value 属性间接实现
  3. 不支持动态创建:不能在运行时动态创建枚举实例
  4. 继承限制:枚举不能继承其他类,但可以实现接口
  5. 魔术方法 :枚举支持 __call__callStatic__invoke 方法

与类常量的对比优势:

特性 枚举 类常量
类型安全 ✅ 是 ❌ 否
自动完成 ✅ 好 ⚠️ 有限
方法支持 ✅ 是 ❌ 否
接口实现 ✅ 是 ❌ 否
遍历所有值 cases() ⚠️ 需要反射

性能提示:

php 复制代码
// 高效比较(使用 identity operator)
if ($status === Status::PUBLISHED) {
    // 因为枚举是单例,所以可以使用 ===
}

// 在 switch/match 中使用
$message = match($status) {
    Status::DRAFT => '草稿',
    Status::PUBLISHED => '已发布',
    Status::ARCHIVED => '已归档',
};

PHP 8.1 枚举提供了类型安全、可读性强且功能丰富的解决方案,适用于需要固定值集合的各种场景。

相关推荐
甲骨文数据库12 小时前
caddy配合PHP(http模式)
php
啊阿狸不会拉杆12 小时前
《计算机网络-自顶向下方法》1.7 计算机网络和因特网的历史 读书笔记
计算机网络·php·perl
智塑未来15 小时前
常用的在线ping测试工具有哪些
服务器·开发语言·php
啊阿狸不会拉杆15 小时前
《计算机网络-自顶向下方法》1.3 网络核心 读书笔记
网络·人工智能·计算机网络·ai·php
171320330计算机毕设编程16 小时前
2027计算机毕设五大方向对比&选题推荐
java·ide·python·算法·django·php·推荐算法
IT小白杨17 小时前
TikTok小店防封号浏览器实战:2026年多店铺环境隔离与账号安全运营技术解析
开发语言·数据库·安全·php·chrome devtools·指纹浏览器
catchadmin17 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.4.0 发布,新增短信服务能力
开发语言·php
Tanshu_API君18 小时前
身份证实名认证接口对接:PHP 接入二要素核验实战
php·api·实名认证·身份证实名认证·身份认证接口·运营商接口·运营商二要素
啊阿狸不会拉杆19 小时前
《计算机网络-自顶向下方法》1.5 协议层次及其服务模型 读书笔记
开发语言·计算机网络·php
斑马13919 小时前
Linux软件编程学习笔记(十)——网络(二)——TCP通信
开发语言·网络·php