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 相关文章推荐
第十三节--对象串行化
Nov 16 PHP
PHP中文件上传的一个问题
Sep 04 PHP
php设计模式 Singleton(单例模式)
Jun 26 PHP
测试php函数的方法
Nov 13 PHP
非常好用的Zend Framework分页类
Jun 25 PHP
php的mkdir()函数创建文件夹比较安全的权限设置方法
Jul 28 PHP
PHP递归复制、移动目录的自定义函数分享
Nov 18 PHP
PHP分页类集锦
Nov 18 PHP
PHP 7.0.2 正式版发布
Jan 08 PHP
PHP实现适用于文件内容操作的分页类
Jun 15 PHP
PHP微信开发之有道翻译
Jun 23 PHP
PHP调用接口用post方法传送json数据的实例
May 31 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
关于手调机和数调机的选择
2021/03/02 无线电
WIN98下Apache1.3.14+PHP4.0.4的安装
2006/10/09 PHP
在PHP中使用Sockets 从Usenet中获取文件
2008/01/10 PHP
php curl模拟post请求小实例
2013/11/13 PHP
php模拟post提交请求调用接口示例解析
2020/08/07 PHP
JS获取scrollHeight问题想到的标准问题
2007/05/27 Javascript
jQuery新闻滚动插件 jquery.roller.js
2011/06/27 Javascript
玩转jQuery按钮 请告诉我你最喜欢哪些?
2012/01/08 Javascript
jQuery 如何先创建、再修改、后添加DOM元素
2014/05/20 Javascript
Node.js中使用Buffer编码、解码二进制数据详解
2014/08/16 Javascript
jQuery简单实现上下,左右滑动的方法
2016/06/01 Javascript
使用DeviceOne实现微信小程序功能
2016/12/29 Javascript
想用好React的你必须要知道的一些事情
2017/07/24 Javascript
表格展示利器 Bootstrap Table实例代码
2017/09/06 Javascript
React中上传图片到七牛的示例代码
2017/10/10 Javascript
vue+iview/elementUi实现城市多选
2019/03/28 Javascript
TypeScript中的方法重载详解
2019/04/12 Javascript
如何搭建一个完整的Vue3.0+ts的项目步骤
2020/10/18 Javascript
微信小程序实现文件预览
2020/10/22 Javascript
[32:26]EG vs IG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python EOL while scanning string literal问题解决方法
2020/09/18 Python
Python搭建FTP服务器的方法示例
2018/01/19 Python
python自动化报告的输出用例详解
2018/05/30 Python
python3调用百度翻译API实现实时翻译
2018/08/16 Python
python中从for循环延申到推导式的具体使用
2019/11/29 Python
python3爬虫GIL修改多线程实例讲解
2020/11/24 Python
澳大利亚最受欢迎的女士度假服装:Kabana Shop
2020/10/10 全球购物
2014年食堂工作总结
2014/11/20 职场文书
大班上学期个人总结
2015/02/13 职场文书
应届生简历自我评价
2015/03/11 职场文书
公司行政助理岗位职责
2015/04/11 职场文书
退休欢送会主持词
2015/07/01 职场文书
交通安全主题班会
2015/08/12 职场文书
初中英语教学随笔
2015/08/15 职场文书
Go Gin实现文件上传下载的示例代码
2021/04/02 Golang
Win11怎么添加用户?Win11添加用户账户的方法
2022/07/15 数码科技