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

相关推荐
石榴树下的七彩鱼2 小时前
智能抠图 API 多语言接入实战:从零到上线的 Python / Java / PHP / JS 完整教程(附避坑指南)
java·python·php·智能抠图·api接入·石榴智能·shiliuai
XS0301064 小时前
Java 基础(九) IO流
java·开发语言·php
独隅4 小时前
此电脑网络位置异常的AD域排错指南
开发语言·php
niucloud-admin4 小时前
PHP SAAS 框架常见问题——怎么添加菜单,添加了菜单不出现怎么回事
php
niucloud-admin4 小时前
PHP SAAS 框架常见问题——本地调试提示输入站点 ID
php
niucloud-admin4 小时前
PHP SAAS 框架常见问题——小程序开发工具代码上传失败问题
php
码云数智-大飞4 小时前
TLS 1.3的革新:更快的速度与更强的安全性
开发语言·php
Johnstons5 小时前
网络诊断工具怎么选:从监控告警到抓包定位的完整方法论
服务器·网络·php·es·抓包分析·网络诊断工具选型与排障方法
aq55356006 小时前
GitSubmodule深度避坑指南
java·开发语言·php
bksczm7 小时前
Linux之基础开发工具(Ubuntu)之apt 、vim
linux·ubuntu·php