本文目录导读:

在 PHP 中,枚举(Enum)是 PHP 8.1 引入的重要特性,以下是使用枚举改善代码质量的各种方式:
基础枚举定义
<?php
// 纯枚举(只有值)
enum UserStatus
{
case Active;
case Inactive;
case Banned;
case Pending;
}
// 带后端值的枚举
enum OrderStatus: string
{
case Pending = 'pending';
case Paid = 'paid';
case Shipped = 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
}
改善魔术数字和字符串
<?php
// ❌ 不好的做法
class UserController
{
public function updateStatus(int $status)
{
// 1,2,3 是什么?难以理解
if ($status === 1) {
// do something
} elseif ($status === 2) {
// do something else
}
}
}
// ✅ 使用枚举改善
class UserController
{
public function updateStatus(UserStatus $status)
{
match($status) {
UserStatus::Active => $this->activateUser(),
UserStatus::Inactive => $this->deactivateUser(),
UserStatus::Banned => $this->banUser(),
UserStatus::Pending => $this->pendingUser(),
};
}
}
带方法的枚举
<?php
enum PaymentMethod: string
{
case CreditCard = 'credit_card';
case PayPal = 'paypal';
case BankTransfer = 'bank_transfer';
// 添加方法
public function getDescription(): string
{
return match($this) {
self::CreditCard => '使用信用卡支付',
self::PayPal => '使用PayPal支付',
self::BankTransfer => '使用银行转账',
};
}
// 检查是否支持特定功能
public function isOnline(): bool
{
return match($this) {
self::CreditCard, self::PayPal => true,
self::BankTransfer => false,
};
}
// 添加静态方法
public static function getOnlineMethods(): array
{
return array_filter(
self::cases(),
fn($method) => $method->isOnline()
);
}
}
状态模式改善
<?php
enum OrderState
{
case Pending;
case Processing;
case Shipped;
case Delivered;
// 状态转换规则
public function canTransitionTo(self $nextState): bool
{
return match($this) {
self::Pending => in_array($nextState, [self::Processing, self::Cancelled]),
self::Processing => in_array($nextState, [self::Shipped, self::Cancelled]),
self::Shipped => in_array($nextState, [self::Delivered, self::Cancelled]),
self::Delivered => false, // 终态
};
}
// 转换方法
public function transitionTo(self $nextState): self
{
if (!$this->canTransitionTo($nextState)) {
throw new InvalidArgumentException(
"不能从 {$this->name} 转换到 {$nextState->name}"
);
}
return $nextState;
}
}
配置与常量定义
<?php
enum AppEnv: string
{
case Development = 'dev';
case Testing = 'test';
case Staging = 'staging';
case Production = 'prod';
public function isProduction(): bool
{
return $this === self::Production;
}
public function getConfig(): array
{
return [
'debug' => !$this->isProduction(),
'cache' => $this->isProduction(),
'log_level' => $this->isProduction() ? 'error' : 'debug',
];
}
}
// 使用
$env = AppEnv::from($_ENV['APP_ENV']);
if (!$env->isProduction()) {
// 开发环境特殊处理
}
数据库字段验证
<?php
// 定义数据库字段的枚举
enum UserRole: string
{
case Admin = 'admin';
case Editor = 'editor';
case Subscriber = 'subscriber';
public function getPermissions(): array
{
return match($this) {
self::Admin => ['*'],
self::Editor => ['create', 'edit', 'delete'],
self::Subscriber => ['read'],
};
}
// 用于验证输入
public static function isValid(string $value): bool
{
return in_array($value, array_column(self::cases(), 'value'));
}
}
// 验证用户输入
$role = UserRole::tryFrom($_POST['role']);
if (!$role) {
throw new InvalidArgumentException('无效的用户角色');
}
业务规则封装
<?php
enum DiscountType
{
case Percentage;
case FixedAmount;
case FreeShipping;
public function calculateDiscount(float $subtotal, float $value): float
{
return match($this) {
self::Percentage => $subtotal * ($value / 100),
self::FixedAmount => min($value, $subtotal),
self::FreeShipping => 0, // 运费折扣单独计算
};
}
public function getValidationRule(): array
{
return match($this) {
self::Percentage => ['min' => 1, 'max' => 100],
self::FixedAmount => ['min' => 0.01, 'max' => PHP_INT_MAX],
self::FreeShipping => ['min' => 0, 'max' => 0],
};
}
}
表单状态处理
<?php
enum CacheDriver: string
{
case File = 'file';
case Redis = 'redis';
case Memcached = 'memcached';
case Database = 'database';
public function getConfig(): array
{
return match($this) {
self::File => ['path' => storage_path('cache')],
self::Redis => ['host' => env('REDIS_HOST'), 'port' => 6379],
self::Memcached => ['host' => env('MEMCACHED_HOST'), 'port' => 11211],
self::Database => ['table' => 'cache'],
};
}
public static function getDefault(): self
{
return self::File;
}
}
表单状态处理
<?php
// 表单验证状态
enum FormValidationState
{
case Valid;
case Invalid;
case Pending;
public function getLabel(): string
{
return match($this) {
self::Valid => '✓ 验证通过',
self::Invalid => '✗ 验证失败',
self::Pending => '⏳ 等待验证',
};
}
public function getCssClass(): string
{
return match($this) {
self::Valid => 'success',
self::Invalid => 'error',
self::Pending => 'pending',
};
}
}
最佳实践总结
<?php
// 1. 使用枚举代替魔法值和魔字符串
// 2. 在方法参数中类型限制
// 3. 结合 match 表达式使用
// 4. 添加行为方法
// 5. 支持静态工厂方法
enum FilePermission
{
case Read;
case Write;
case Execute;
public function toOctal(): int
{
return match($this) {
self::Read => 4,
self::Write => 2,
self::Execute => 1,
};
}
public static function fromOctal(int $value): array
{
$permissions = [];
foreach (self::cases() as $permission) {
if ($value & $permission->toOctal()) {
$permissions[] = $permission;
}
}
return $permissions;
}
}
// 使用示例
$permissions = [FilePermission::Read, FilePermission::Write];
$octal = array_reduce($permissions,
fn($carry, $perm) => $carry | $perm->toOctal(), 0);
// $octal = 6
主要优势
- 类型安全:编译器会检查类型
- 代码清晰:自文档化的代码
- 减少错误:避免拼写错误和无效值
- 易于维护:集中管理相关的常量
- IDE支持:自动补全和类型提示
- 模式匹配:与 match 表达式完美配合
使用枚举能显著提高代码质量和可维护性,特别适合处理状态机、配置选项和业务规则等场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播