PHP 8.1 枚举类型完全指南:类型安全的常量管理新方案
Orion K Lv6

引言

PHP 8.1引入的枚举(Enums)是我期待已久的特性。作为一个经常需要处理状态、类型、权限等固定值集合的开发者,枚举让我的代码更加类型安全和易于维护。经过一年多的实践,我想分享一些枚举的实际应用经验。

从常量到枚举的进化

传统的常量方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 传统方式:容易出错,缺乏类型安全
class OrderStatus {
const PENDING = 'pending';
const PROCESSING = 'processing';
const SHIPPED = 'shipped';
const DELIVERED = 'delivered';
const CANCELLED = 'cancelled';
}

// 使用时容易出错
function processOrder(string $status) {
if ($status === OrderStatus::PENDING) {
// 处理待处理订单
} elseif ($status === 'procesing') { // 拼写错误!
// 这个分支永远不会执行
}
}

// 调用时没有类型检查
processOrder('invalid_status'); // 运行时才发现错误

使用枚举的现代方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 现代方式:类型安全,IDE友好
enum OrderStatus: string {
case PENDING = 'pending';
case PROCESSING = 'processing';
case SHIPPED = 'shipped';
case DELIVERED = 'delivered';
case CANCELLED = 'cancelled';
}

// 类型安全的函数
function processOrder(OrderStatus $status): void {
match($status) {
OrderStatus::PENDING => $this->handlePending(),
OrderStatus::PROCESSING => $this->handleProcessing(),
OrderStatus::SHIPPED => $this->handleShipped(),
OrderStatus::DELIVERED => $this->handleDelivered(),
OrderStatus::CANCELLED => $this->handleCancelled(),
};
}

// 编译时类型检查
processOrder(OrderStatus::PENDING); // ✓ 正确
// processOrder('invalid'); // ✗ 类型错误

枚举的基本类型

1. 纯枚举(Pure Enums)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum Direction {
case NORTH;
case SOUTH;
case EAST;
case WEST;
}

// 使用示例
function move(Direction $direction): void {
match($direction) {
Direction::NORTH => $this->moveUp(),
Direction::SOUTH => $this->moveDown(),
Direction::EAST => $this->moveRight(),
Direction::WEST => $this->moveLeft(),
};
}

$player->move(Direction::NORTH);

2. 支持值的枚举(Backed Enums)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 字符串支持的枚举
enum UserRole: string {
case ADMIN = 'admin';
case MODERATOR = 'moderator';
case USER = 'user';
case GUEST = 'guest';
}

// 整数支持的枚举
enum Priority: int {
case LOW = 1;
case MEDIUM = 2;
case HIGH = 3;
case URGENT = 4;
}

// 获取枚举值
echo UserRole::ADMIN->value; // 输出: admin
echo Priority::HIGH->value; // 输出: 3

实际应用场景

1. 订单状态管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
enum OrderStatus: string {
case PENDING = 'pending';
case CONFIRMED = 'confirmed';
case PROCESSING = 'processing';
case SHIPPED = 'shipped';
case DELIVERED = 'delivered';
case CANCELLED = 'cancelled';
case REFUNDED = 'refunded';

public function getLabel(): string {
return match($this) {
self::PENDING => '待处理',
self::CONFIRMED => '已确认',
self::PROCESSING => '处理中',
self::SHIPPED => '已发货',
self::DELIVERED => '已送达',
self::CANCELLED => '已取消',
self::REFUNDED => '已退款',
};
}

public function canTransitionTo(OrderStatus $newStatus): bool {
return match($this) {
self::PENDING => in_array($newStatus, [self::CONFIRMED, self::CANCELLED]),
self::CONFIRMED => in_array($newStatus, [self::PROCESSING, self::CANCELLED]),
self::PROCESSING => in_array($newStatus, [self::SHIPPED, self::CANCELLED]),
self::SHIPPED => in_array($newStatus, [self::DELIVERED]),
self::DELIVERED => in_array($newStatus, [self::REFUNDED]),
self::CANCELLED, self::REFUNDED => false,
};
}

public function isActive(): bool {
return !in_array($this, [self::CANCELLED, self::REFUNDED, self::DELIVERED]);
}
}

// 订单类
class Order {
public function __construct(
private string $id,
private OrderStatus $status = OrderStatus::PENDING
) {}

public function updateStatus(OrderStatus $newStatus): void {
if (!$this->status->canTransitionTo($newStatus)) {
throw new InvalidArgumentException(
"Cannot transition from {$this->status->value} to {$newStatus->value}"
);
}

$this->status = $newStatus;
$this->logStatusChange($newStatus);
}

public function getStatus(): OrderStatus {
return $this->status;
}

public function getStatusLabel(): string {
return $this->status->getLabel();
}
}

2. HTTP状态码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
enum HttpStatus: int {
// 2xx Success
case OK = 200;
case CREATED = 201;
case ACCEPTED = 202;
case NO_CONTENT = 204;

// 3xx Redirection
case MOVED_PERMANENTLY = 301;
case FOUND = 302;
case NOT_MODIFIED = 304;

// 4xx Client Error
case BAD_REQUEST = 400;
case UNAUTHORIZED = 401;
case FORBIDDEN = 403;
case NOT_FOUND = 404;
case METHOD_NOT_ALLOWED = 405;
case UNPROCESSABLE_ENTITY = 422;

// 5xx Server Error
case INTERNAL_SERVER_ERROR = 500;
case BAD_GATEWAY = 502;
case SERVICE_UNAVAILABLE = 503;

public function getMessage(): string {
return match($this) {
self::OK => 'OK',
self::CREATED => 'Created',
self::ACCEPTED => 'Accepted',
self::NO_CONTENT => 'No Content',
self::MOVED_PERMANENTLY => 'Moved Permanently',
self::FOUND => 'Found',
self::NOT_MODIFIED => 'Not Modified',
self::BAD_REQUEST => 'Bad Request',
self::UNAUTHORIZED => 'Unauthorized',
self::FORBIDDEN => 'Forbidden',
self::NOT_FOUND => 'Not Found',
self::METHOD_NOT_ALLOWED => 'Method Not Allowed',
self::UNPROCESSABLE_ENTITY => 'Unprocessable Entity',
self::INTERNAL_SERVER_ERROR => 'Internal Server Error',
self::BAD_GATEWAY => 'Bad Gateway',
self::SERVICE_UNAVAILABLE => 'Service Unavailable',
};
}

public function isSuccess(): bool {
return $this->value >= 200 && $this->value < 300;
}

public function isRedirection(): bool {
return $this->value >= 300 && $this->value < 400;
}

public function isClientError(): bool {
return $this->value >= 400 && $this->value < 500;
}

public function isServerError(): bool {
return $this->value >= 500 && $this->value < 600;
}
}

// API响应类
class ApiResponse {
public function __construct(
private mixed $data,
private HttpStatus $status = HttpStatus::OK,
private array $headers = []
) {}

public function send(): void {
http_response_code($this->status->value);

foreach ($this->headers as $name => $value) {
header("$name: $value");
}

header('Content-Type: application/json');

echo json_encode([
'status' => $this->status->value,
'message' => $this->status->getMessage(),
'data' => $this->data
]);
}
}

3. 权限系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
enum Permission: string {
case USER_READ = 'user.read';
case USER_CREATE = 'user.create';
case USER_UPDATE = 'user.update';
case USER_DELETE = 'user.delete';

case POST_READ = 'post.read';
case POST_CREATE = 'post.create';
case POST_UPDATE = 'post.update';
case POST_DELETE = 'post.delete';

case ADMIN_PANEL = 'admin.panel';
case SYSTEM_CONFIG = 'system.config';

public function getGroup(): string {
return explode('.', $this->value)[0];
}

public function getAction(): string {
return explode('.', $this->value)[1];
}

public function getDescription(): string {
return match($this) {
self::USER_READ => '查看用户信息',
self::USER_CREATE => '创建用户',
self::USER_UPDATE => '更新用户信息',
self::USER_DELETE => '删除用户',
self::POST_READ => '查看文章',
self::POST_CREATE => '创建文章',
self::POST_UPDATE => '更新文章',
self::POST_DELETE => '删除文章',
self::ADMIN_PANEL => '访问管理面板',
self::SYSTEM_CONFIG => '系统配置管理',
};
}

public static function getByGroup(string $group): array {
return array_filter(
self::cases(),
fn(Permission $permission) => $permission->getGroup() === $group
);
}
}

// 角色枚举
enum Role: string {
case SUPER_ADMIN = 'super_admin';
case ADMIN = 'admin';
case MODERATOR = 'moderator';
case USER = 'user';
case GUEST = 'guest';

public function getPermissions(): array {
return match($this) {
self::SUPER_ADMIN => Permission::cases(),
self::ADMIN => [
Permission::USER_READ,
Permission::USER_CREATE,
Permission::USER_UPDATE,
Permission::POST_READ,
Permission::POST_CREATE,
Permission::POST_UPDATE,
Permission::POST_DELETE,
Permission::ADMIN_PANEL,
],
self::MODERATOR => [
Permission::USER_READ,
Permission::POST_READ,
Permission::POST_UPDATE,
Permission::POST_DELETE,
],
self::USER => [
Permission::POST_READ,
Permission::POST_CREATE,
],
self::GUEST => [
Permission::POST_READ,
],
};
}

public function hasPermission(Permission $permission): bool {
return in_array($permission, $this->getPermissions());
}

public function getLevel(): int {
return match($this) {
self::SUPER_ADMIN => 5,
self::ADMIN => 4,
self::MODERATOR => 3,
self::USER => 2,
self::GUEST => 1,
};
}
}

// 用户类
class User {
public function __construct(
private string $id,
private string $name,
private Role $role = Role::USER
) {}

public function hasPermission(Permission $permission): bool {
return $this->role->hasPermission($permission);
}

public function can(Permission $permission): bool {
return $this->hasPermission($permission);
}

public function getRole(): Role {
return $this->role;
}
}

4. 日志级别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
enum LogLevel: string {
case EMERGENCY = 'emergency';
case ALERT = 'alert';
case CRITICAL = 'critical';
case ERROR = 'error';
case WARNING = 'warning';
case NOTICE = 'notice';
case INFO = 'info';
case DEBUG = 'debug';

public function getSeverity(): int {
return match($this) {
self::EMERGENCY => 8,
self::ALERT => 7,
self::CRITICAL => 6,
self::ERROR => 5,
self::WARNING => 4,
self::NOTICE => 3,
self::INFO => 2,
self::DEBUG => 1,
};
}

public function getColor(): string {
return match($this) {
self::EMERGENCY, self::ALERT, self::CRITICAL => 'red',
self::ERROR => 'orange',
self::WARNING => 'yellow',
self::NOTICE => 'blue',
self::INFO => 'green',
self::DEBUG => 'gray',
};
}

public function shouldLog(LogLevel $minLevel): bool {
return $this->getSeverity() >= $minLevel->getSeverity();
}
}

// 日志记录器
class Logger {
public function __construct(
private LogLevel $minLevel = LogLevel::INFO
) {}

public function log(LogLevel $level, string $message, array $context = []): void {
if (!$level->shouldLog($this->minLevel)) {
return;
}

$timestamp = date('Y-m-d H:i:s');
$levelName = strtoupper($level->value);
$contextStr = empty($context) ? '' : ' ' . json_encode($context);

echo "[$timestamp] $levelName: $message$contextStr\n";
}

public function emergency(string $message, array $context = []): void {
$this->log(LogLevel::EMERGENCY, $message, $context);
}

public function error(string $message, array $context = []): void {
$this->log(LogLevel::ERROR, $message, $context);
}

public function warning(string $message, array $context = []): void {
$this->log(LogLevel::WARNING, $message, $context);
}

public function info(string $message, array $context = []): void {
$this->log(LogLevel::INFO, $message, $context);
}

public function debug(string $message, array $context = []): void {
$this->log(LogLevel::DEBUG, $message, $context);
}
}

枚举的高级特性

1. 枚举方法和静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
enum Planet: float {
case MERCURY = 3.303e+23;
case VENUS = 4.869e+24;
case EARTH = 5.976e+24;
case MARS = 6.421e+23;
case JUPITER = 1.9e+27;
case SATURN = 5.688e+26;
case URANUS = 8.686e+25;
case NEPTUNE = 1.024e+26;

// 实例方法
public function surfaceGravity(float $radius): float {
$G = 6.67300E-11;
return $G * $this->value / ($radius * $radius);
}

public function surfaceWeight(float $mass, float $radius): float {
return $mass * $this->surfaceGravity($radius);
}

// 静态方法
public static function getByMass(float $mass): ?self {
foreach (self::cases() as $planet) {
if (abs($planet->value - $mass) < 1e+22) {
return $planet;
}
}
return null;
}

public static function getTerrestrialPlanets(): array {
return [self::MERCURY, self::VENUS, self::EARTH, self::MARS];
}

public static function getGasGiants(): array {
return [self::JUPITER, self::SATURN, self::URANUS, self::NEPTUNE];
}
}

// 使用示例
$earthWeight = 70; // kg
$earthRadius = 6.371e6; // meters

foreach (Planet::cases() as $planet) {
$weight = $planet->surfaceWeight($earthWeight, $earthRadius);
echo "Weight on {$planet->name}: " . number_format($weight, 2) . " kg\n";
}

2. 枚举接口实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
interface Colorable {
public function getColor(): string;
public function getHexColor(): string;
}

enum Status: string implements Colorable {
case ACTIVE = 'active';
case INACTIVE = 'inactive';
case PENDING = 'pending';
case SUSPENDED = 'suspended';

public function getColor(): string {
return match($this) {
self::ACTIVE => 'green',
self::INACTIVE => 'gray',
self::PENDING => 'yellow',
self::SUSPENDED => 'red',
};
}

public function getHexColor(): string {
return match($this) {
self::ACTIVE => '#28a745',
self::INACTIVE => '#6c757d',
self::PENDING => '#ffc107',
self::SUSPENDED => '#dc3545',
};
}

public function getIcon(): string {
return match($this) {
self::ACTIVE => '✅',
self::INACTIVE => '⚫',
self::PENDING => '⏳',
self::SUSPENDED => '🚫',
};
}
}

3. 枚举特征(Traits)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
trait EnumHelper {
public static function names(): array {
return array_map(fn($case) => $case->name, self::cases());
}

public static function values(): array {
return array_map(fn($case) => $case->value, self::cases());
}

public static function random(): self {
$cases = self::cases();
return $cases[array_rand($cases)];
}

public static function fromName(string $name): ?self {
foreach (self::cases() as $case) {
if ($case->name === $name) {
return $case;
}
}
return null;
}
}

enum Color: string {
use EnumHelper;

case RED = '#ff0000';
case GREEN = '#00ff00';
case BLUE = '#0000ff';
case YELLOW = '#ffff00';
case PURPLE = '#800080';
}

// 使用示例
$colors = Color::names(); // ['RED', 'GREEN', 'BLUE', 'YELLOW', 'PURPLE']
$values = Color::values(); // ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#800080']
$random = Color::random(); // 随机颜色
$red = Color::fromName('RED'); // Color::RED

枚举的序列化和反序列化

1. JSON序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
enum TaskStatus: string implements JsonSerializable {
case TODO = 'todo';
case IN_PROGRESS = 'in_progress';
case DONE = 'done';
case CANCELLED = 'cancelled';

public function jsonSerialize(): string {
return $this->value;
}

public static function fromJson(string $value): self {
return self::from($value);
}

public function getDisplayName(): string {
return match($this) {
self::TODO => '待办',
self::IN_PROGRESS => '进行中',
self::DONE => '已完成',
self::CANCELLED => '已取消',
};
}
}

class Task {
public function __construct(
public string $title,
public TaskStatus $status = TaskStatus::TODO
) {}

public function toArray(): array {
return [
'title' => $this->title,
'status' => $this->status->value,
'status_display' => $this->status->getDisplayName()
];
}

public static function fromArray(array $data): self {
return new self(
title: $data['title'],
status: TaskStatus::from($data['status'])
);
}
}

2. 数据库存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
enum UserType: string {
case INDIVIDUAL = 'individual';
case BUSINESS = 'business';
case ENTERPRISE = 'enterprise';

public function getFeatures(): array {
return match($this) {
self::INDIVIDUAL => ['basic_features'],
self::BUSINESS => ['basic_features', 'team_collaboration'],
self::ENTERPRISE => ['basic_features', 'team_collaboration', 'advanced_analytics', 'priority_support'],
};
}

public function getMaxUsers(): int {
return match($this) {
self::INDIVIDUAL => 1,
self::BUSINESS => 50,
self::ENTERPRISE => PHP_INT_MAX,
};
}
}

// 数据库模型
class User {
public function __construct(
public int $id,
public string $name,
public string $email,
public UserType $type
) {}

// 保存到数据库
public function save(): void {
$sql = "INSERT INTO users (name, email, type) VALUES (?, ?, ?)";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->name, $this->email, $this->type->value]);
}

// 从数据库加载
public static function find(int $id): ?self {
$sql = "SELECT * FROM users WHERE id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$id]);
$data = $stmt->fetch();

if (!$data) {
return null;
}

return new self(
id: $data['id'],
name: $data['name'],
email: $data['email'],
type: UserType::from($data['type'])
);
}
}

性能和内存使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 性能测试:枚举 vs 常量
class PerformanceTest {
// 传统常量
const STATUS_ACTIVE = 'active';
const STATUS_INACTIVE = 'inactive';

public function testConstants(): void {
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$status = self::STATUS_ACTIVE;
$this->processConstant($status);
}
$end = microtime(true);
echo "Constants: " . ($end - $start) . " seconds\n";
}

public function testEnums(): void {
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$status = Status::ACTIVE;
$this->processEnum($status);
}
$end = microtime(true);
echo "Enums: " . ($end - $start) . " seconds\n";
}

private function processConstant(string $status): void {
// 处理逻辑
}

private function processEnum(Status $status): void {
// 处理逻辑
}
}

// 测试结果:
// Constants: 0.045 seconds
// Enums: 0.048 seconds
// 性能差异约6%,可以接受

最佳实践

1. 命名规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 好的命名
enum OrderStatus: string {
case PENDING = 'pending';
case CONFIRMED = 'confirmed';
case SHIPPED = 'shipped';
}

enum HttpMethod: string {
case GET = 'GET';
case POST = 'POST';
case PUT = 'PUT';
case DELETE = 'DELETE';
}

// 避免的命名
enum BadNaming: string {
case status1 = 'pending'; // 不清晰
case STATUS_2 = 'confirmed'; // 不一致
case Shipped = 'shipped'; // 大小写不一致
}

2. 方法设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
enum Priority: int {
case LOW = 1;
case MEDIUM = 2;
case HIGH = 3;
case URGENT = 4;

// 好的方法设计
public function isHigherThan(Priority $other): bool {
return $this->value > $other->value;
}

public function getLabel(): string {
return match($this) {
self::LOW => '低优先级',
self::MEDIUM => '中优先级',
self::HIGH => '高优先级',
self::URGENT => '紧急',
};
}

public static function fromString(string $priority): self {
return match(strtolower($priority)) {
'low', '低' => self::LOW,
'medium', '中' => self::MEDIUM,
'high', '高' => self::HIGH,
'urgent', '紧急' => self::URGENT,
default => throw new InvalidArgumentException("Unknown priority: $priority")
};
}
}

3. 错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
enum Currency: string {
case USD = 'USD';
case EUR = 'EUR';
case CNY = 'CNY';
case JPY = 'JPY';

public static function tryFrom(string $value): ?self {
try {
return self::from($value);
} catch (ValueError) {
return null;
}
}

public static function fromWithDefault(string $value, self $default = self::USD): self {
return self::tryFrom($value) ?? $default;
}

public function getSymbol(): string {
return match($this) {
self::USD => '$',
self::EUR => '€',
self::CNY => '¥',
self::JPY => '¥',
};
}
}

// 安全的使用方式
$currency = Currency::tryFrom($userInput);
if ($currency === null) {
throw new InvalidArgumentException('Invalid currency');
}

// 或者使用默认值
$currency = Currency::fromWithDefault($userInput, Currency::USD);

迁移策略

从常量迁移到枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 第一步:创建枚举,保持常量
class OrderStatus {
// 保持现有常量以兼容旧代码
const PENDING = 'pending';
const PROCESSING = 'processing';
const SHIPPED = 'shipped';
const DELIVERED = 'delivered';
}

enum OrderStatusEnum: string {
case PENDING = 'pending';
case PROCESSING = 'processing';
case SHIPPED = 'shipped';
case DELIVERED = 'delivered';

// 提供转换方法
public static function fromConstant(string $constant): self {
return self::from($constant);
}

public function toConstant(): string {
return $this->value;
}
}

// 第二步:逐步替换使用
function processOrder(OrderStatusEnum|string $status): void {
if (is_string($status)) {
$status = OrderStatusEnum::from($status);
}

// 使用枚举逻辑
match($status) {
OrderStatusEnum::PENDING => $this->handlePending(),
// ...
};
}

// 第三步:完全迁移后移除常量类

总结

PHP 8.1的枚举是一个强大的特性,它为我们提供了类型安全的常量管理方案。在实际项目中,我发现枚举特别适用于:

  1. 状态管理:订单状态、用户状态等
  2. 配置选项:日志级别、权限类型等
  3. API设计:HTTP状态码、错误类型等
  4. 业务逻辑:优先级、类别分类等

使用枚举的好处:

  • 类型安全:编译时检查,减少运行时错误
  • IDE支持:自动补全和重构
  • 可扩展性:可以添加方法和实现接口
  • 可读性:代码更加清晰和自文档化

注意事项:

  • 选择合适的枚举类型(纯枚举 vs 支持值的枚举)
  • 合理设计枚举方法
  • 考虑向后兼容性
  • 注意性能影响(通常可以忽略)

枚举让PHP代码更加现代化和类型安全,强烈推荐在新项目中使用!

本站由 提供部署服务