本文目录导读:

- 方法1:PHP 8.1+ 原生枚举(推荐)
- 方法2:使用 Trait 复用枚举方法
- 方法3:Backed Enum 添加额外数据
- 方法4:模拟枚举(PHP 8.1 之前)
- 方法5:使用第三方库 MyCLabs Enum
- 最佳实践建议
在PHP中,有多种方式可以实现“枚举添加”(即给枚举添加自定义方法或属性),以下是几种主流方法:
方法1:PHP 8.1+ 原生枚举(推荐)
<?php
enum Status: string
{
case PENDING = 'pending';
case APPROVED = 'approved';
case REJECTED = 'rejected';
// 添加自定义方法
public function label(): string
{
return match($this) {
self::PENDING => '等待审核',
self::APPROVED => '已通过',
self::REJECTED => '已拒绝',
};
}
// 添加静态方法
public static function activeStatuses(): array
{
return [self::APPROVED];
}
// 添加判断方法
public function isActive(): bool
{
return $this === self::APPROVED;
}
}
// 使用示例
$status = Status::PENDING;
echo $status->label(); // 输出:等待审核
echo Status::APPROVED->isActive() ? '是' : '否'; // 输出:是
方法2:使用 Trait 复用枚举方法
<?php
trait EnumHelpers
{
public function isActive(): bool
{
return in_array($this, self::activeStatuses());
}
public static function names(): array
{
return array_column(self::cases(), 'name');
}
}
enum OrderStatus: int
{
use EnumHelpers;
case NEW = 0;
case PROCESSING = 1;
case COMPLETED = 2;
case CANCELLED = 3;
// 自定义方法
public function label(): string
{
return match($this) {
self::NEW => '新订单',
self::PROCESSING => '处理中',
self::COMPLETED => '已完成',
self::CANCELLED => '已取消',
};
}
// 静态方法
public static function activeStatuses(): array
{
return [self::NEW, self::PROCESSING];
}
}
// 使用
$status = OrderStatus::NEW;
echo $status->isActive() ? '活跃' : '非活跃'; // 输出:活跃
方法3:Backed Enum 添加额外数据
<?php
enum PaymentMethod: string
{
case WECHAT = 'wechat';
case ALIPAY = 'alipay';
case BANK = 'bank';
// 添加额外属性方法
public function displayName(): string
{
return match($this) {
self::WECHAT => '微信支付',
self::ALIPAY => '支付宝',
self::BANK => '银行转账',
};
}
public function fee(): float
{
return match($this) {
self::WECHAT => 0.006,
self::ALIPAY => 0.005,
self::BANK => 0.01,
};
}
// 工厂方法
public static function fromName(string $name): self
{
return match($name) {
'wechat' => self::WECHAT,
'alipay' => self::ALIPAY,
'bank' => self::BANK,
default => throw new \InvalidArgumentException("Invalid payment method: $name"),
};
}
}
// 使用
$method = PaymentMethod::WECHAT;
echo "{$method->displayName()} 手续费: {$method->fee()}";
方法4:模拟枚举(PHP 8.1 之前)
<?php
class UserRole
{
const ADMIN = 'admin';
const USER = 'user';
const GUEST = 'guest';
private string $value;
private function __construct(string $value)
{
$this->value = $value;
}
// 工厂方法
public static function from(string $value): self
{
return new self($value);
}
// 自定义方法
public function label(): string
{
return match($this->value) {
self::ADMIN => '管理员',
self::USER => '普通用户',
self::GUEST => '访客',
default => '未知',
};
}
public function hasPermission(string $permission): bool
{
return match($this->value) {
self::ADMIN => true,
self::USER => in_array($permission, ['read', 'write']),
self::GUEST => $permission === 'read',
default => false,
};
}
// 获取所有枚举值
public static function values(): array
{
return [self::ADMIN, self::USER, self::GUEST];
}
}
// 使用
$role = UserRole::from(UserRole::ADMIN);
echo $role->label(); // 输出:管理员
方法5:使用第三方库 MyCLabs Enum
<?php
// 安装: composer require myclabs/php-enum
use MyCLabs\Enum\Enum;
class Color extends Enum
{
const RED = '#ff0000';
const GREEN = '#00ff00';
const BLUE = '#0000ff';
// 添加自定义方法
public function lighten(): Color
{
return new self(self::WHITE);
}
}
class Status extends Enum
{
const PENDING = 0;
const ACTIVE = 1;
const DISABLED = 2;
public function isActive(): bool
{
return $this->value === self::ACTIVE;
}
}
// 使用
$status = new Status(Status::ACTIVE);
echo $status->isActive() ? '活跃' : '非活跃';
最佳实践建议
- PHP 8.1+:优先使用原生枚举
- 类型安全:为枚举添加类型(string 或 int)
- 方法命名:保持方法名称清晰且语义化
- 不要滥用:枚举方法应该是逻辑相关的
- Trait 复用:当多个枚举需要相同方法时考虑 Trait
这样你就可以为 PHP 枚举灵活地添加各种自定义方法和属性了。