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

相关推荐
BingoGo1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082855 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe5 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5