PHP 枚举类型的管理与设计知识点总结

今天来分享下如何管理 PHP 的枚举类型。

一种常见的方式是,使用常量来代表枚举类型

const YES = '是';

const NO = '否';

可以在这个基础上更进一步,将其封装成类,以便于管理

class BoolEnum {

  const YES = '是';

  const NO = '否';

}

现在,我们希望能通过方法来动态调用对应的枚举类型

BoolEnum::YES(); // 是

BoolEnum::NO(); // 否

也可以批量获取枚举类型

BoolEnum::toArray(); // ['Yes' => '是', 'No' => '否']

下面来实现上面列举的功能。

定义基本的枚举基类,让所有的枚举类都继承该抽象基类。

abstract class Enum

{  

  // 获取所有枚举类型

  public static function toArray(){

    // 通过反射获取常量

    $reflection = new \ReflectionClass(static::class);

    $contants = $reflection->getConstants();

    // 返回对应的常量

    return $contants;

  }

  // 动态调用属性

  public static function __callStatic($name, $arguments)

  {

    $arr = static::toArray();

    if(isset($arr[$name])){

      return $arr[$name];

    }

    throw new \BadMethodCallException("找不到对应的枚举值 {$name}");

  }

}

class BoolEnum extends Enum

{

  const YES = '是';

  const NO = '否';

}

利用反射,可以获取到所有的枚举类型。同时,利用魔术方法则可以实现对属性的动态调用。这里要注意的是,反射会消耗较多的资源,因此,对 toArray 方法进行重构,增加一个缓存变量来缓存获取到的枚举类型,避免重复使用反射。

abstract class Enum

{  

  protected static $cache = [];

  public static function toArray(){

    $class = static::class;

    // 第一次获取,就通过反射来获取

    if(! isset(static::$cache[$class])){

      $reflection = new \ReflectionClass(static::class);

      static::$cache[$class] = $reflection->getConstants();

    }

    return static::$cache[$class];

  }

}

现在考虑更多的使用场景,比如用实例来代表特定枚举类型

$yes = new BoolEnum("是");

echo $yes; // "是"

实现如下

abstract Enum 

{

  protected $value;

  public function __construct($value)

  {  

    if ($value instanceof static) {

      $value = $value->getValue();

    }

    if(! $this->isValid($value)){

      throw new \UnexpectedValueException("$value 不属于该枚举值" . static::class);

    }

    $this->value = $value;

  }

  // 获取实例对应的键

  public function getKey(){

    return array_search($this->value, static::toArray(), true);

  }

  // 获取实例对应的值

  public function getValue()

  {

    return $this->value;

  }

  // 允许字符串形式输出

  public function __toString()

  {

    return $this->value;

  }

  // 验证值是否合法

  public function isValid($value)

  {

   $arr = static::toArray();

   return in_array($value, $arr, true);

  }

  // 验证键是否合法

  public function isValidKey($key)

  {

   $arr = static::toArray();

   return array_key_exists($key, $arr);

  }

}

这样做可避免用户使用非法的枚举类型的值

$user->banned = '非法值'; // 可能不会报错

$yes = new BoolEnum("非法值"); // 将会抛出异常

$user->banned = $yes;

或者作为参数类型限定

function setUserStatus(BoolEnum $boolEnum){

  $user->banned = $boolEnum;

}

PHP 作为一门弱类型语言,参数限定的不足会导致很多不可预期的错误发生,通过使用枚举类,我们进一步加强了参数限定的功能,同时,管理枚举类型也更加的方便统一。

以上就是本次介绍的全部相关知识点,感谢大家的学习和对我们的支持。

(0)

相关推荐

  • PHP中Enum(枚举)用法实例详解

    本文实例讲述了PHP中Enum(枚举)用法.分享给大家供大家参考,具体如下: PHP其实有Enum类库的,需要安装perl扩展,所以不是php的标准扩展,因此代码的实现需要运行的php环境支持. (1)扩展类库SplEnum类.该类的摘要如下: SplEnum extends SplType { /* Constants */ const NULL __default = null ; /* 方法 */ public array getConstList ([ bool $include_def

  • PHP 枚举类型的管理与设计知识点总结

    今天来分享下如何管理 PHP 的枚举类型. 一种常见的方式是,使用常量来代表枚举类型 const YES = '是'; const NO = '否'; 可以在这个基础上更进一步,将其封装成类,以便于管理 class BoolEnum { const YES = '是'; const NO = '否'; } 现在,我们希望能通过方法来动态调用对应的枚举类型 BoolEnum::YES(); // 是 BoolEnum::NO(); // 否 也可以批量获取枚举类型 BoolEnum::toArra

  • 秒懂Java枚举类型(enum)

    理解枚举类型 枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性.安全性以及便捷性.下面先来看看什么是枚举?如何定义枚举? 枚举的定义 上述的常量定义常量的方式称为int枚举模式,这样的定义方式并没有什么错,但它存在许多不足,如在类型安全和使用方便性上并没有多少好处,如果存在定义int值相同的变量,混淆的几率还是很大的,编译器也不会提出任何警告,因此这种方式在枚举

  • C#中可枚举类型详解

    枚举是迭代一个集合中的数据项的过程. 我们经常使用的大多数集合实际上都已经实现了枚举的接口IEnumerable和IEnumerator接口,这样才能使用foreach迭代,有些是含有某种抽象了枚举细节的接口:ArrayList类型有索引,BitArray有Get方法,哈希表和字典有键和值..........其实他们都已经实现了IEnumerable和IEnumerator接口.所以一切的集合和数组都可以用IEnumerable或者IEnumerable<T>接口来定义. IEnumerabl

  • Java的枚举类型使用方法详解

    1.背景 在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量.之前我们通常利用public final static 方法定义的代码如下,分别用1 表示春天,2表示夏天,3表示秋天,4表示冬天. public class Season { public static final int SPRING = 1; public static final int SUMMER = 2; public static final int AUTUMN = 3; publ

  • 全面解读Java中的枚举类型enum的使用

    关于枚举 大多数地方写的枚举都是给一个枚举然后例子就开始switch,可是我想说,我代码里头来源的数据不太可能就是枚举,通常是字符串或数字,比如一个SQL我解析后首先判定SQL类型,通过截取SQL的token,截取出来可能是SELECT.DELETE.UPDATE.INSERT.ALTER等等,但是都是字符串,此时我想用枚举就不行了,我要将字符串转换成枚举怎么转呢,类似的情况还有从数据库取出数据根据一些类型做判定,从页面传入数据,根据不同的类型做不同的操作,但是都是字符串,不是枚举,悲剧的是我很

  • Android开发笔记之:用Enum(枚举类型)取代整数集的应用详解

    在Android的API中可以发现有很多用整数集来作为参数的地方,先来看一下实例.LinearLayout是大家所熟知的一个UI基本元素,它里面有一个方向的属性,可以通过以下方法来设置: 复制代码 代码如下: LinearLayout.setOrientation(int); 使用的时候,通常都是这样: 复制代码 代码如下: LinearLayout.setOrientation(LinearLayout.HORIZONTAL);LinearLayout.setOrientation(Linea

  • C#权限管理和设计浅谈

    此文主要想和大家分享的是这段时间,对权限管理和设计的断断续续的思考学习,和个人的一些软件开发等方面的看法. 提到'权限管理和设计',大家可能会第一时间想到这园子里的 吉日嘎拉,在这方面他可以算是'大牛'或专家 --他的'通用权限管理系统',究竟做的怎样,看看他的博客就差不多可以知道了(貌似我在给他做推广,呵呵...,but in fact,is not),别的暂且不敢说,最起码可以看出他研究的比较深入和狂热,其系统也具有一定的'成熟度',用他的话来说--就是在努力做到他的极致.他做的是通用权限管

  • 扒一扒 Java 中的枚举类型

    前言 在 Java 中, 枚举, 也称为枚举类型, 其是一种特殊的数据类型, 它使得变量能够称为一组预定义的常量. 其目的是强制编译时类型安全. 枚举类更加直观,类型安全.使用常量会有以下几个缺陷: 1. 类型不安全.若一个方法中要求传入季节这个参数,用常量的话,形参就是int类型,开发者传入任意类型的int类型值就行,但是如果是枚举类型的话,就只能传入枚举类中包含的对象. 2. 没有命名空间.开发者要在命名的时候以SEASON_开头,这样另外一个开发者再看这段代码的时候,才知道这四个常量分别代

  • C#如何给枚举类型增加一个描述特性详解

    前言 相信很多人对枚举并不陌生,枚举可以很方便和直观的管理一组特定值.如果我们在页面上直接输出我们希望匹配的汉语意思或则其他满足我们需求的语句就更好了,当然,通常小伙伴们都会再页面上if(enum==1) "我是一个枚举"或者switch(enum)这种方式解决. 枚举的优点: <1>枚举可以使代码更易于维护,有助于确保给变量指定合法的.期望的值. <2>枚举使代码更清晰,允许用描述性的名称表示整数值,而不是用含义模糊的数来表示. <3>枚举使代码更

  • Golang表示枚举类型的详细讲解

    枚举,是一种重要的数据类型,由一组键值对组成,通常用来在编程语言中充当常量的标识符.在主流行编程语言如 c. java 等,都有原生支持.在 go 中,大家却找不到 enum 或者其它直接用来声明枚举类型的关键字.从熟悉其它编程语言的开发者转用 go 编程,刚开始会比较难接受这种情况.其实,如果你看到如何在 go 中表示枚举类型时,可能会感受到 go 语言设计者对简洁性.问题考虑的深度,是一般资浅工程师无法比拟的. 其实,在 go 语言设计者的眼里,enum 本质是常量,为什么要多余一个关键字呢

随机推荐