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


Posted in PHP onFebruary 13, 2020

今天来分享下如何管理 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 作为一门弱类型语言,参数限定的不足会导致很多不可预期的错误发生,通过使用枚举类,我们进一步加强了参数限定的功能,同时,管理枚举类型也更加的方便统一。

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

PHP 相关文章推荐
深入理解PHP之require/include顺序 推荐
Jan 02 PHP
php不使用插件导出excel的简单方法
Mar 04 PHP
PHP下通过QRCode类库创建中间带网站LOGO的二维码
Jul 12 PHP
PHP学习笔记(一) 简单了解PHP
Aug 04 PHP
WordPress中"无法将上传的文件移动至"错误的解决方法
Jul 01 PHP
PHP Web木马扫描器代码分享
Sep 06 PHP
php实现购物车功能(下)
Jan 05 PHP
Laravel 实现密码重置功能
Feb 23 PHP
yii2安装详细流程
May 23 PHP
php使用curl模拟多线程实现批处理功能示例
Jul 25 PHP
ThinkPHP5.1的权限控制怎么写?分享一个AUTH权限控制
Mar 09 PHP
如何判断微信付款码和支付宝付款码
Apr 01 PHP
PHP+ajax实现上传、删除、修改单张图片及后台处理逻辑操作详解
Feb 12 #PHP
分享8个Laravel模型时间戳使用技巧小结
Feb 12 #PHP
tp5.0框架隐藏index.php入口文件及模块和控制器的方法分析
Feb 11 #PHP
thinkphp5框架路由原理与用法详解
Feb 11 #PHP
php数组指针函数功能及用法示例
Feb 11 #PHP
PHP实现单例模式建立数据库连接的方法分析
Feb 11 #PHP
php-7.3.6 编译安装过程
Feb 11 #PHP
You might like
PHP标准库(PHP SPL)详解
2019/03/16 PHP
关于Anemometer图形化显示MySQL慢日志的工具搭建及使用的详细介绍
2020/07/13 PHP
Javascript 读后台cookie代码
2008/09/15 Javascript
IE6 fixed的完美解决方案
2011/03/31 Javascript
JQuery为textarea添加maxlength属性并且兼容IE
2013/04/25 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
javascript计算用户打开网页的停留时间
2014/01/09 Javascript
JavaScript原生对象常用方法总结(推荐)
2016/05/13 Javascript
JS模拟的Map类实现方法
2016/06/17 Javascript
浅谈js中StringBuffer类的实现方法及使用
2016/09/02 Javascript
js中用cssText设置css样式的简单方法
2016/09/19 Javascript
jQuery分页插件jquery.pagination.js使用方法解析
2017/02/09 Javascript
JavaScript注册时密码强度校验代码
2017/06/30 Javascript
JavaScript 程序错误Cannot use 'in' operator to search的解决方法
2017/07/10 Javascript
微信小程序 五星评分的实现实例
2017/08/04 Javascript
vue mint-ui tabbar变组件使用
2018/05/04 Javascript
详解create-react-app 2.0版本如何启用装饰器语法
2018/10/23 Javascript
如何在JavaScript中创建具有多个空格的字符串?
2020/02/23 Javascript
Vue列表循环从指定下标开始的多种解决方案
2020/04/08 Javascript
python生成IP段的方法
2015/07/07 Python
Django与遗留的数据库整合的方法指南
2015/07/24 Python
Python实现的文本编辑器功能示例
2017/06/30 Python
Python简单计算数组元素平均值的方法示例
2017/12/26 Python
Python Unittest自动化单元测试框架详解
2018/04/04 Python
Python发送邮件测试报告操作实例详解
2018/12/08 Python
Django 实现图片上传和显示过程详解
2019/07/18 Python
Python 列表去重去除空字符的例子
2019/07/20 Python
ubuntu上安装python的实例方法
2019/09/30 Python
python写文件时覆盖原来的实例方法
2020/07/22 Python
纯CSS3绘制打火机动画火焰效果
2016/07/18 HTML / CSS
交通事故私了协议书
2014/04/16 职场文书
幼儿园健康教育方案
2014/06/14 职场文书
伊琍体标语
2014/06/25 职场文书
党政领导班子民主生活会整改措施
2014/09/18 职场文书
用人单位聘用意向书
2015/05/11 职场文书
Python FuzzyWuzzy实现模糊匹配
2022/04/28 Python