PHP 8.1 枚举(Enums)详解

目录

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

什么是枚举?

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

基本语法

// 定义纯值枚举
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)

// 整数类型的枚举
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)

// 回退枚举可以具有标量值(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";
}

枚举方法

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

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;

接口实现

枚举可以实现接口:

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:订单状态管理

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:权限系统

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:配置管理

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()⚠️ 需要反射

性能提示:

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

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

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值