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

相关推荐
rookieﻬ°3 小时前
PHP框架漏洞
开发语言·php
CQU_JIAKE9 小时前
3.21【A】
开发语言·php
上海云盾-小余10 小时前
云主机安全加固:从系统、网络到应用的零信任配置
网络·安全·php
Eric.Lee202112 小时前
查看ubuntu机器正在使用的网络端口
网络·ubuntu·php
jinanwuhuaguo12 小时前
OpenClaw安全使用实践全景深度指南:从“裸奔龙虾”到“可信数字堡垒”的体系化构建
开发语言·php
xiangpanf13 小时前
Laravel学习指南:从入门到精通
php·laravel
南梦浅16 小时前
全过程步骤(从零到高可用企业网络)
开发语言·网络·php
xiangpanf16 小时前
Laravel 9.X新特性全解析
php·laravel
xiangpanf16 小时前
Laravel与ThinkPHP框架深度对比
php·laravel
hongtianzai17 小时前
Laravel7.x十大核心特性解析
java·c语言·开发语言·golang·php