当前位置: 首页 > 后端技术 > PHP

PHP枚举类ENUM的实现

时间:2023-03-30 06:19:07 PHP

概述阅读本文档时,假定您已经了解枚举的基本概念。否则您可能会对文档的某些部分感到困惑。每个项目都可以使用枚举。在PHP中,通常使用一组常量或一组静态变量来代替枚举。但是在属性之间存在组合或关联关系的复杂场景中,使用枚举会大大降低开发和维护成本。PHP官方通过SPL类库为我们提供了枚举类SplEnum,但是首先需要通过扩展的方式安装,其次通常需要重新打包才能使用好。本枚举类参考JAVA枚举,实现了一个简单易用但功能强大的枚举类库。安装composerrequirephpenum/phpenumdocument定义枚举时,只有public或protected修饰的const关键字定义的常量才会被枚举类识别,public可以省略。所有枚举类都是抽象类。枚举类的构造方法是受保护的,不能实例化。枚举单例只能通过枚举类提供的方法获取。由于PHP的浮点类型的精度,当枚举属性包含浮点类型值时,任何基于浮点类型的比较或查找的结果都不应该被信任。具体参见浮点精度说明。当同一个枚举对象包含相同的枚举常量值时,在定义和使用过程中应使用前缀进行分组,否则不要相信使用相同的枚举常量值比较或查找结果。基本枚举源码测试用例的基本枚举是单值类型枚举。枚举类不对枚举常量值强制类型约束,但是你应该让每一组枚举常量值的类型始终相同。基本枚举中所有的getter方法都省略了get,其实是保留给它的子类实现getter。基本枚举提供了以下方法name:获取枚举的名称value:获取枚举的值equals:判断当前枚举是否等于给定的枚举nameEquals:判断枚举的名称是否等于给定的namevalueEquals:判断枚举值是否等于给定值names:[静态方法]获取枚举的所有名称,并以数据的形式返回。如果指定了名称前缀,则只返回指定名称前缀值的一部分:【静态方法】获取所有枚举值,并以数据的形式返回。数组的键是枚举名称。如果指定了名称前缀,则只返回指定名称前缀的部分枚举:【静态方法】获取所有枚举实例,使用data数组的key为枚举名称。如果指定了名称前缀,则只返回指定名称前缀的部分。hasName:[静态方法]判断枚举名称是否存在。ParthasValue:[静态方法]判断枚举常量值是否存在。如果指定了名称前缀,则只判断指定名称前缀的部分。byName:[静态方法]根据枚举名称获取枚举实例。如果指定了名称前缀,则只通过Value判断指定名称前缀的部分:【静态方法】根据枚举常量值获取枚举实例。如果指定了名称前缀,则只判断指定名称前缀的部分。count:【静态方法】返回枚举属性的个数,如果指定了名称前缀,则只对指定名称前缀的部分进行判断。下面以用户枚举的定义为例,介绍基本枚举的使用。下面的用户枚举包含了两组用户性别和状态的枚举常量值,使用了SEX和STATUS前缀。/***@methodstaticselfSEX_MAN*@methodstaticselfSEX_WOMAN*@methodstaticselfSTATUS_NORMAL*@methodstaticselfSTATUS_INVALID*/classUserEnumextends\PhpEnum\Enum{constSEX_MAN=1;//1表示性别为男性constSEX_WOMAN=2;//2表示性别为女性constSTATUS_NORMAL=1;//1表示正常状态constSTATUS_INVALID=9;//9表示无效状态}枚举对象可以通过下面的方法获取,枚举对象在第一次创建后会被缓存起来,任何方法获取的枚举对象都是一样的。第一种方法是最有效和推荐的。用户枚举::SEX_MAN();//如果实例还没有创建,只会创建当前枚举常量值的实例并返回,推荐使用UserEnum::byName('SEX_MAN');//如果存在未创建的实例,则创建所有未创建的枚举常量值的实例,然后返回当前实例UserEnum::byValue(1,'SEX');//如果当前组中有未创建的实例,则将当前组中所有未创建的枚举常量值创建实例,然后返回当前实例UserEnum::enums('SEX')['SEX_MAN'];//如果当前组有未创建的实例,则创建当前组中所有未创建的枚举常量值的实例,然后返回当前实例列表枚举源代码测试用例列表枚举继承自基枚举,是一个多值类型枚举,其中多值是通过数组元素实现的,所以枚举常量值的类型必须定义为数组,并且数组的长度也是通过list枚举类的length方法指定的.列表枚举需要在枚举常量中为每个数组元素定义一个私有属性作为载体,然后通过重写列表枚举类的ListEnum方法将接收到的数据元素赋值给固定的属性,通常使用list进行分配。列表枚举需要为每个载体属性提供getter方法,但不应该提供setter方法以防止枚举结构被破坏。列表枚举继承了基础枚举的所有方法,但是由于列表枚举常量值的类型是数组,valueEquals值hasValuebyValue这些使用枚举常量值的方法通常意义不大。列表枚举提供了以下方法ListEnum:与列表枚举类同名的方法,接受当前枚举常量值,需要重写length:【静态方法】返回列表枚举常量值元素个数,需要重写下面以城市枚举为例,介绍列表枚举的用法。下面城市枚举中的枚举常量长度为3,包括省份代码、城市代码、城市名/***@methodstaticselfPROVINCE_LIAONING*@methodstaticselfCITY_BEIJING*@methodstaticselfCITY_SHENYANG*@methodstaticselfCITY_DALIAN*/classCityEnumextends\PhpEnum\ListEnum{constPROVINCE_LIAONING=['0','22000','辽宁'];constCITY_BEIJING=['1100100000'','北京'];constCITY_SHENYANG=['22000','210100','沉阳'];constCITY_DALIAN=['22000','210200','大连'];私人$省;私人$城市;私人的名字;protectedfinalfunctionListEnum($list){list($this->province,$this->city,$this->name)=$list;}publicfinalstaticfunctionlength(){return3;}publicfunctiongetProvince(){return$this->province;}公共函数getCity(){返回$这个->城市;}publicfunctiongetName(){return$this->name;}}获取城市枚举属性值CityEnum::PROVINCE_LIAONING()->getProvince();//string(1)"0"CityEnum::PROVINCE_LIAONING()->getCity();//string(5)"22000"CityEnum::PROVINCE_LIAONING()->getName();//string(8)"辽宁"分别获取城市枚举所有省市CityEnum::enums('PROVINCE');//获取所有省份枚举CityEnum::enums('province',false);//获取所有省份枚举CityEnum::enums('CITY');//获取所有城市EnumerationCityEnum::enums('city',false);//获取所有城市枚举数组枚举源码测试用例数组枚举继承于list枚举,是double值类型的枚举,数组枚举常量值总是有两个元素,第一个元素作为key,第二个元素为用作值数组。value在枚举中的意义将不再是枚举常量值,而是常量值中的第二个元素。valueEqualshasValuebyValue这些继承和基本Enumeration方法已被覆盖,以使用常量值的第二个元素作为值。数组枚举提供了以下方法getKey:获取数据枚举常量的第一个元素值getValue:获取数据枚举常量的第二个元素值keyEquals:判断数据枚举常量的第一个元素的值与给定的值是否一致是否相等valueEquals:判断数据枚举常量值的第二个元素是否等于给定值specified如果指定了名称前缀,则只返回指定名称前缀的部分如果指定了名称前缀,则只返回指定名称前缀的部分getEnums:[静态方法]获取数组枚举的所有实例,并以数据的形式返回。如果指定了名称前缀,则只返回指定名称前缀的部分hasKey:[静态方法]判断数据枚举常量值的第一个元素是否存在,如果指定了名称前缀,则只返回判断有指定名称前缀的部分。hasValue:【静态方法】判断数据枚举常量值的第二个元素是否存在,如果指定了名称前缀,则只判断指定名称前缀的部分,通过Key:【静态方法】获取枚举实例根据数据枚举常量第一个元素的值,如果指定了名称前缀,则只根据Value判断指定名称前缀的部分:【静态方法】根据数据枚举常量的第二个元素获取枚举实例value,如果指定了名字前缀,则只判断指定名字前缀的部分。下面以统一格式错误码为例,介绍数组枚举的用法。下面的错误码枚举中,key为错误码,value为错误描述/***@methodstaticselfOK*@methodstaticselfUNKNOWN_ERROR*@methodstaticselfERROR_DATA_VALIDATION*@methodstaticselfERROR_USER_INVALID*@方法静态自身ERROR_CONFIG_ERROR*/classErrorCodeEnumextends\PhpEnum\ArrayEnum{constOK=['0','ok'];constUNKNOWN_ERROR=['99999','未知错误'];constERROR_DATA_VALIDATION=['10000','给定的数据无效'];constERROR_USER_INVALID=['20000','用户凭据无效'];constERROR_CONFIG_ERROR=['30000','Configinfoiserror'];}错误码和错误描述可以通过以下方式获取ErrorCodeEnum::OK()->getKey();//string(1)"0"ErrorCodeEnum::OK()->getValue();//string(2)"ok"返回统一的错误码,需要自定义异常类classApiExceptionextendsException{private$data;公共函数__construct(ErrorCodeEnum$enum,$data=''){parent::__construct($enum->getValue(),$enum->getKey());$this->data=$data;}publicfunctiontoArray(){return['code'=>$this->getCode(),'msg'=>$this->getMessage(),'data'=>$this->data];}}返回失败结果时,抛出自定义异常并指定错误码枚举thrownewApiException(ErrorCodeEnum::ERROR_DATA_VALIDATION());//{"code":10000,"msg":"Thegivendatawasinvalid","data":""}thrownewApiException(ErrorCodeEnum::ERROR_USER_INVALID(),'Thisisdata');//{"code":20000,"msg":"Usercredentialswasinvalid","data":"Thisisdata"}成功的结果应该单独定义return['code'=>ErrorCodeEnum::OK()->getKey(),'msg'=>ErrorCodeEnum::OK()->getValue(),'data'=>'',];//{"code":"0","msg":"ok","data":""}