Skip to content

Version 1.3 CN

yinfuyuan edited this page Jan 4, 2021 · 2 revisions

PHP 枚举

PHPEnum是为PHP开发人员准备的枚举类库。其想法来源于 Java枚举 并利用PHP的特性实现了单值枚举和多值枚举。PHPEnum与Laravel集成非常方便。

此版本依赖 PHP version 5.6+

安装

composer require phpenum/phpenum 1.3

枚举类

PHPEnum包含三个核心枚举类,分别为:

  • 基础枚举 - 测试用例 这是一个单值枚举类,也是一个基础类,枚举类都会继承此类
  • 列表枚举 - 测试用例 这是一个基于单值枚举类实现的多值枚举类,可以定义任意数量的属性
  • 数组枚举 - 测试用例 这是一个多值枚举的实现类,基于最常用的两个属性值的枚举场景预定义了key和value两个属性

这里所说的单值和多值的值是指属性值,其实枚举本身没有单值和多值之分,但由于语言特性,没有很好的办法将其在一个类中实现。

快速开始

让我们通过一个表示用户性别的枚举为例,来了解各个枚举的用法和区别

数组枚举

定义数组枚举时需要注意所有的常量值都需要定义为有两个元素的数组,否则系统将会抛出一个异常

首先我们基于数组枚举来定义用户性别枚举,它的定义方式与普通的常量定义一样:

class UserGenderEnum extends \PhpEnum\ArrayEnum
{
    const MALE   = [1, 'male'];
    const FEMALE = [2, 'female'];
}

当我们定义好用户性别枚举后,让我们看看数组枚举为我们提供了哪些功能:

  1. 当我们想获取一个男性的枚举实例时,我们可以通过下面任意一个方法,获取到的枚举实例始终为同一个

     UserGenderEnum::MALE() // 只会缓存当前实例
     UserGenderEnum::ofEnumName('MALE') // 会缓存所有实例
     UserGenderEnum::ofKey(1) // 会缓存所有实例
     UserGenderEnum::ofValue('male') // 会缓存所有实例
    
  2. 当我们想获取枚举名称或属性值时,我们可以这样做

     UserGenderEnum::MALE()->name() // string(4) "MALE"
     UserGenderEnum::MALE()->getKey() // int(1)
     UserGenderEnum::MALE()->getValue() // string(4) "male"
    
  3. 当我们想比较一个属性时,我们可以这样做

     UserGenderEnum::MALE()->enumNameEquals('MALE') // bool(true)
     UserGenderEnum::MALE()->keyEquals(1) // bool(true)
     UserGenderEnum::MALE()->valueEquals('male') // bool(true)
    
  4. 当我们想要验证前端传递的数据是否正确时,枚举可以很快速的实现它

     UserGenderEnum::containsEnumName('MALE') // int(1) 返回查找到的枚举数量
     UserGenderEnum::containsKey(1) // int(1) 返回查找到的枚举数量
     UserGenderEnum::containsValue('male') // int(1) 返回查找到的枚举数量
    
  5. 可能有的时候我们无法得到一个具体的值去验证,比如在Laravel验证器中,我们需要得到一个字符串进行验证,只需要这么做

     implode(',', UserGenderEnum::names()) // string(11) "MALE,FEMALE"
     implode(',', UserGenderEnum::getProperties('key')) // string(3) "1,2"
     implode(',', UserGenderEnum::getProperties('value')) // string(11) "male,female"
    

通过上面的示例我们了解到了数组枚举部分功能的用法,但你可能觉得预定义的属性名称key和value 在不同的场景下对理解它们代表什么含义并不友好,那么接下来你需要了解下列表枚举的使用。

列表枚举

定义列表枚举时需要注意必须要定义protected修饰的构造方法listEnumConstruct,枚举常量值必须为非空数组且长度要与构造方法参数的个数完全一致,否则系统将会抛出一个异常

这次让我们基于列表枚举来定义用户性别枚举, 这次除了定义常量外,我们使用了自定义的属性名称id和name,并通过构造方法为其赋值

class UserGenderEnum extends \PhpEnum\ListEnum
{
    const MALE   = [1, 'male'];
    const FEMALE = [2, 'female'];

    private $id;
    private $name;

    protected function listEnumConstruct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}

当我们定义好用户性别枚举后,上面我们在数组枚举中演示过的功能在这里也全都生效,只是需要将key换成id,将value换成name,如:

  1. 当我们想获取一个男性的枚举实例时,我们可以通过下面任意一个方法,获取到的枚举实例始终为同一个。

     UserGenderEnum::MALE() // 只会缓存当前实例
     UserGenderEnum::ofEnumName('MALE') // 会缓存所有实例
     UserGenderEnum::ofId(1) // 会缓存所有实例
     UserGenderEnum::ofName('male') // 会缓存所有实例
    
  2. 当我们想获取枚举名称或属性值时,我们可以这样做

     UserGenderEnum::MALE()->name() // string(4) "MALE"
     UserGenderEnum::MALE()->getId() // int(1)
     UserGenderEnum::MALE()->getName() // string(4) "male"
    
  3. 当我们想比较一个属性时,我们可以这样做

     UserGenderEnum::MALE()->enumNameEquals('MALE') // bool(true)
     UserGenderEnum::MALE()->idEquals(1) // bool(true)
     UserGenderEnum::MALE()->nameEquals('male') // bool(true)
    
  4. 当我们想要验证前端传递的数据是否正确时,枚举可以很快速的实现它

     UserGenderEnum::containsEnumName('MALE') // int(1) 返回查找到的枚举数量
     UserGenderEnum::containsId(1) // int(1) 返回查找到的枚举数量
     UserGenderEnum::containsName('male') // int(1) 返回查找到的枚举数量
    
  5. 可能有的时候我们无法得到一个具体的值去验证,比如在Laravel验证器中,我们需要得到一个字符串进行验证,只需要这么做

     implode(',', UserGenderEnum::names()) // string(11) "MALE,FEMALE"
     implode(',', UserGenderEnum::getProperties('id')) // string(3) "1,2"
     implode(',', UserGenderEnum::getProperties('name')) // string(11) "male,female"
    

列表枚举的实现多是参考JAVA枚举,但由于JAVA本身是在语言层面对枚举功能做的支持,定义JAVA枚举元素就是在定义构造方法,这些在PHP中无法支持, 所以只能用数组来代替,有兴趣可以看一下 Java枚举

基础枚举

基础枚举是单值枚举,只有属性名称name和属性值value,基础枚举不限制属性值的类型,但同时属性值始终作为一个整体,无法再细分

这次让我们再基于基础枚举来定义用户性别枚举,基础枚举的定义同数组枚举的定义相同

class UserGenderEnum extends \PhpEnum\Enum
{
    const MALE   = [1, 'male'];
    const FEMALE = [2, 'female'];
}

当我们定义好用户性别枚举后,让我们看看基础枚举为我们提供了哪些功能(注意基础枚举中的属性值[1, 'male']只能作为一个整体使用):

  1. 当我们想获取一个男性的枚举实例时,我们可以通过下面任意一个方法,获取到的枚举实例始终为同一个

     UserGenderEnum::MALE() // 只会缓存当前实例
     UserGenderEnum::ofEnumName('MALE') // 会缓存所有实例
     UserGenderEnum::ofEnumValue([1, 'male']) // 会缓存所有实例
    
  2. 当我们想获取枚举名称或属性值时,我们可以这样做

     UserGenderEnum::MALE()->name() // string(4) "MALE"
     UserGenderEnum::MALE()->value() // array(2) {[0]=>int(1)[1]=>string(4) "male"}
    
  3. 当我们想比较一个属性时,我们可以这样做

     UserGenderEnum::MALE()->enumNameEquals('MALE') // bool(true)
     UserGenderEnum::MALE()->enumValueEquals([1, 'male']) // bool(true)
    
  4. 当我们想要验证前端传递的数据是否正确时,枚举可以很快速的实现它

     UserGenderEnum::containsEnumName('MALE') // int(1) 返回查找到的枚举数量
     UserGenderEnum::containsValue([1, 'male']') // int(1) 返回查找到的枚举数量
    
  5. 当我们需要得到一个字符串时,可以这样做

     implode(',', UserGenderEnum::names()) // string(11) "MALE,FEMALE"
    

到这里枚举常用的功能就介绍完了,三种不同类型的枚举提供不同的功能,要根据实际的使用场景进行选择使用

Clone this wiki locally