PHP8.1新特性Enum像Java一样使用枚举

了解Java的Php程序员都知道,PHP一直以来是没有Enum这个特性的,虽然有一个扩展的类可以实现类似的功能,但总感觉不是“原生”,刚好现在需要用到PHP8.1版本,这里记录一下对PHP的枚举Enum的简单使用。

1、先定义一个枚举Trait,因为PHP的枚举不能扩展。

<?php

namespace App\Traits;

trait EnumExtend
{
    // 以array返回枚举的key
    public static function keys(): array
    {
        return array_map(function ($item) {
            return $item->name;
        }, self::cases());
    }
    
    // 以['key' => 'value', ...]形式返回枚举内容,可供select组件选择使用
    public static function keyValues(): array
    {
        $result = [];
        foreach (self::cases() as $item) {
            $result[$item->name] = $item->value;
        }
        return $result;
    }

    // 判断持久层返回的是否相同
    public function equal(string $value): bool
    {
        return self::tryFrom($value) === $this;
    }
    // 判断string key是否包含在枚举里面
    public static function include(string $value): bool
    {
        return in_array($value, self::keys());
    }
    // 判读多个string key是否全部包含在枚举里面
    public static function includeAll(array $names): bool
    {
        $keys = self::keys();
        foreach ($names as $name) {
            if (!in_array($name, $keys)) {
                return false;
            }
        }
        return true;
    }
}

2、定义枚举

<?php declare(strict_types=1);

namespace App\Enums;

use App\Traits\EnumExtend;

/**
 * 商品类型
 */
enum ProductType: string
{
    use EnumExtend;

    case PRODUCT = '商品';
    case SERVICE = '服务';
    case CONSUMPTION = '消耗品';
}

3、具体应用

<?php

// 列表枚举的 key
ProductType::keys();
// output: ['PRODUCT', 'SERVICE', 'CONSUMPTION']

// 列出枚举的key => value
ProductType::keyValues();
// output: ['PRODUCT' => '商品', 'SERVICE' => '服务', 'CONSUMPTION' => '消耗品']
// 这里我用于前端Select组件选择,保存key值在数据库中,如:ProductModel.product_type = 'PRODUCT'
// 在前端列表等显示界面,通过product_type = 'PRODUCT'显示出“商品”


// 简单判断类型
if (ProductType::PRODUCT->equal(ProductModel.product_type)) {
    // ...
} else if (ProductType::SERVICE->equal(ProductModel.product_type)) {
    // ...
} else {}

// 判断是否包含key,如:前端输入的值是否合法
$formData = ['product_type' => 'PRODUCT'];
ProductType::include($formData['product_type']);
// output: true

// 判断是否包含多个key,如:前端输入的多个值是否合法
$formData = ['product_type' => ['PRODUCT', 'PRODUCT2']];
ProductType::includeAll($formData['product_type']);
// output: false

4、其它应用

前端的使用基本满足简单应用的情况了。如果还有更复杂的,可以深入了解。

例如使用PHP的注解结合枚举使用:

4.1、定义注解

<?php

namespace App\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_CLASS_CONSTANT)]
class Description
{
    private $value;
    public function __construct($value = ''){
        $this->value = $value;
    }
}

4.2、在枚举中使用 

<?php declare(strict_types=1);

namespace App\Enums;

use App\Traits\EnumExtend;
use App\Attributes\Description;

/**
 * 商品类型
 */
enum ProductType: int
{
    use EnumExtend;

    #[Description('商品')]
    case PRODUCT = 1;
    #[Description('服务')]
    case SERVICE = 2;
    #[Description('消耗品')]
    case CONSUMPTION = 3;


    public function getDescription() {
        $ref = new \ReflectionEnumUnitCase(self::class, $this->name);
        $attributes = $ref->getAttributes();
        foreach ($attributes as $attribute) {
            $args = $attribute->getArguments();
            return $args[0];
        }
        return '';
    }

    public static function keyValues(): array
    {
        $result = [];
        foreach (self::cases() as $item) {
            $result[$item->value] = $item->getDescription();
        }
        return $result;
    }
}


ProductType::PRODUCT->name; // PRODUCT
ProductType::PRODUCT->value; // 1
ProductType::PRODUCT->getDescription(); // 商品
ProductType::keyValues(); // [1 => '商品', 2 => '服务', 3 => '消耗品']

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值