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新手谈谈我的学习心得
Feb 25 PHP
dedecms中常见问题修改方法总结
Mar 21 PHP
谈PHP生成静态页面分析 模板+缓存+写文件
Aug 17 PHP
php设计模式 State (状态模式)
Jun 26 PHP
file_get_contents获取不到网页内容的解决方法
Mar 07 PHP
php设计模式之单例、多例设计模式的应用分析
Jun 30 PHP
使用Curl进行抓取远程内容时url中文编码问题示例探讨
Oct 29 PHP
PDO防注入原理分析以及使用PDO的注意事项总结
Oct 23 PHP
PHP5.3以上版本安装ZendOptimizer扩展
Mar 27 PHP
简单介绍PHP的责任链编程模式
Aug 11 PHP
PHP页面输出搜索后跳转下一页的处理方法
Sep 30 PHP
TP5框架实现自定义分页样式的方法示例
Apr 05 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实现链结人气统计
2006/10/09 PHP
php使用COPY函数更新配置文件的方法
2015/06/18 PHP
ajax+php实现无刷新验证手机号的实例
2017/12/22 PHP
JavaScript XML和string相互转化实现代码
2011/07/04 Javascript
浅析JavaScript中两种类型的全局对象/函数
2013/12/05 Javascript
JavaScript原型及原型链终极详解
2016/01/04 Javascript
jquery拖拽排序简单实现方法(效果增强版)
2016/02/16 Javascript
JavaScript 浏览器兼容性总结及常用浏览器兼容性分析
2016/03/30 Javascript
实例详解ECMAScript5中新增的Array方法
2016/04/05 Javascript
jQuery+CSS3+Html5实现弹出层效果实例代码(附源码下载)
2016/05/16 Javascript
基于Bootstrap实现图片轮播效果
2016/05/22 Javascript
使用plupload自定义参数实现多文件上传
2016/07/19 Javascript
JavaScript实现瀑布流以及加载效果
2017/02/11 Javascript
Vue工程模板文件 webpack打包配置方法
2017/12/26 Javascript
JS和Canvas实现图片的预览压缩和上传功能
2018/03/30 Javascript
JS+HTML5实现获取手机验证码倒计时按钮
2018/08/08 Javascript
vue中的router-view组件的使用教程
2018/10/23 Javascript
详解如何使用微信小程序云函数发送短信验证码
2019/03/13 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
laydate只显示时分 不显示秒的功能实现方法
2019/09/28 Javascript
微信小程序webSocket的使用方法
2020/02/20 Javascript
JavaScript Html实现移动端红包雨功能页面
2021/01/10 Javascript
[58:42]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第一局
2016/02/27 DOTA
将Emacs打造成强大的Python代码编辑工具
2015/11/20 Python
Python中matplotlib中文乱码解决办法
2017/05/12 Python
Python3 socket同步通信简单示例
2017/06/07 Python
python 去除txt文本中的空格、数字、特定字母等方法
2018/07/24 Python
Python实现iOS自动化打包详解步骤
2018/10/03 Python
python实现将文件夹下面的不是以py文件结尾的文件都过滤掉的方法
2018/10/21 Python
python super函数使用方法详解
2020/02/14 Python
python TCP包注入方式
2020/05/05 Python
HTML5不支持frameset的两种解决方法
2016/11/14 HTML / CSS
奥巴马演讲稿
2014/01/08 职场文书
一年级下册数学教学反思
2016/02/16 职场文书
oracle索引总结
2021/09/25 Oracle
mysql通过group by分组取最大时间对应数据的两种有效方法
2022/09/23 MySQL