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 相关文章推荐
mysql下创建字段并设置主键的php代码
May 16 PHP
在PHP中实现Javascript的escape()函数代码
Aug 08 PHP
php设计模式 Decorator(装饰模式)
Jun 26 PHP
PHP中对于浮点型的数据需要用不同的方法解决
Mar 11 PHP
Codeigniter发送邮件的方法
Mar 19 PHP
php结合安卓客户端实现查询交互实例
May 05 PHP
PHP类的特性实例分析
Sep 28 PHP
PHP单态模式简单用法示例
Nov 16 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
为Plesk PHP7启用Oracle OCI8扩展方法总结
Mar 29 PHP
php抽象方法和普通方法的区别点总结
Oct 13 PHP
PHP使用Redis队列执行定时任务实例讲解
Mar 24 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
Zend Framework教程之Zend_Layout布局助手详解
2016/03/04 PHP
cakephp常见知识点汇总
2017/02/24 PHP
PHP PDO和消息队列的个人理解与应用实例分析
2019/11/25 PHP
JavaScript获取和设置CheckBox状态的简单方法
2013/07/05 Javascript
浅谈javascript中for in 和 for each in的区别
2015/04/23 Javascript
jquery Deferred 快速解决异步回调的问题
2016/04/05 Javascript
Vuejs第七篇之Vuejs过渡动画案例全面解析
2016/09/05 Javascript
详解Jquery Easyui的验证扩展
2017/01/09 Javascript
JS仿Base.js实现的继承示例
2017/04/07 Javascript
利用js的闭包原理做对象封装及调用方法
2017/04/07 Javascript
jQuery设置图片等比例缩小的方法
2017/04/29 jQuery
详解nodeJS之路径PATH模块
2017/05/31 NodeJs
vue组件从开发到发布的实现步骤
2018/11/11 Javascript
vue中typescript装饰器的使用方法超实用教程
2019/06/17 Javascript
微信小程序自定义菜单切换栏tabbar组件代码实例
2019/12/30 Javascript
详解javascript void(0)
2020/07/13 Javascript
使用python绘制人人网好友关系图示例
2014/04/01 Python
Python xlrd读取excel日期类型的2种方法
2015/04/28 Python
Java中重定向输出流实现用文件记录程序日志
2015/06/12 Python
利用python实现xml与数据库读取转换的方法
2017/06/17 Python
Python实现字典排序、按照list中字典的某个key排序的方法示例
2018/12/18 Python
Python自动抢红包教程详解
2019/06/11 Python
keras中的History对象用法
2020/06/19 Python
大数据分析用java还是Python
2020/07/06 Python
Python用K-means聚类算法进行客户分群的实现
2020/08/23 Python
结合CSS3的布局新特征谈谈常见布局方法
2016/01/22 HTML / CSS
浅谈css3中的前缀
2016/07/20 HTML / CSS
深入理解HTML的FormData对象
2016/05/17 HTML / CSS
Shopee马来西亚:随拍即卖,最佳行动电商拍卖平台
2017/06/05 全球购物
Windows和Linux动态库应用异同
2016/07/28 面试题
求职面试个人自我评价
2014/02/28 职场文书
活动总结的格式
2014/05/07 职场文书
大一新生期末自我评价
2014/09/12 职场文书
首次购房证明
2015/06/19 职场文书
导游词之宁夏贺兰山岩画
2019/11/08 职场文书