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版(5)
Oct 09 PHP
PHP中通过HTTP_USER_AGENT判断是否为手机移动终端的函数代码
Feb 14 PHP
php生成txt文件标题及内容的方法
Jan 16 PHP
显示youtube视频缩略图和Vimeo视频缩略图代码分享
Feb 13 PHP
ThinkPHP3.1新特性之内容解析输出详解
Jun 19 PHP
PHP设置头信息及取得返回头信息的方法
Jan 25 PHP
php获取文件后缀的9种方法
Mar 22 PHP
使用ltrace工具跟踪PHP库函数调用的方法
Apr 25 PHP
php mysql procedure实现获取多个结果集的方法【基于thinkPHP】
Nov 09 PHP
THinkPHP获取客户端IP与IP地址查询的方法
Nov 14 PHP
浅析PHP中的 inet_pton 网络函数
Dec 16 PHP
PHP基于ip2long实现IP转换整形
Dec 11 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抽象工厂模式(Elgg)
2010/03/21 PHP
PHP验证码无法显示的原因及解决办法
2017/08/11 PHP
PHP命名空间定义与用法实例分析
2019/08/14 PHP
msn上的tab功能Firefox对childNodes处理的一个BUG
2008/01/21 Javascript
jQuery使用slideUp方法实现控制元素缓慢收起
2015/03/27 Javascript
vue开发心得和技巧分享
2016/10/27 Javascript
javascript 正则表达式分组、断言详解
2017/04/20 Javascript
深入理解vue Render函数
2017/07/19 Javascript
jQuery实现动态加载select下拉列表项功能示例
2018/05/31 jQuery
微信小程序使用setData修改数组中单个对象的方法分析
2018/12/30 Javascript
Node.js console控制台简单用法分析
2019/01/04 Javascript
详解a标签添加onclick事件的几种方式
2019/03/29 Javascript
express异步函数异常捕获示例详解
2020/11/30 Javascript
python学习教程之使用py2exe打包
2017/09/24 Python
Python入门学习指南分享
2018/04/11 Python
python 删除非空文件夹的实例
2018/04/26 Python
Pycharm配置远程调试的方法步骤
2018/12/17 Python
selenium 多窗口切换的实现(windows)
2020/01/18 Python
python删除某个目录文件夹的方法
2020/05/26 Python
带你学习Python如何实现回归树模型
2020/07/16 Python
Python中的面向接口编程示例详解
2021/01/17 Python
Pytorch自定义Dataset和DataLoader去除不存在和空数据的操作
2021/03/03 Python
HTML5中语义化 b 和 i 标签
2008/10/17 HTML / CSS
HTML5触摸事件(touchstart、touchmove和touchend)的实现
2020/05/08 HTML / CSS
法国一家芭蕾舞鞋公司:Repetto
2018/11/12 全球购物
什么样的创业计划书可行性高?
2014/02/01 职场文书
法律进企业活动方案
2014/03/04 职场文书
婚纱店策划方案
2014/05/22 职场文书
空气环保标语
2014/06/12 职场文书
计算机应用应届生求职信
2014/07/12 职场文书
会员卡清退活动总结
2014/08/27 职场文书
房屋出租协议书范本(标准版)
2014/09/24 职场文书
2015年毕业生个人自荐书
2015/03/24 职场文书
小米11和iphone12哪个值得买?小米11对比iphone12评测
2021/04/21 数码科技
Spring Bean的实例化之属性注入源码剖析过程
2021/06/13 Java/Android