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 28 PHP
解决FastCGI 进程超过了配置的活动超时时限的问题
Jul 03 PHP
php解析json数据实例
Aug 19 PHP
php实现根据字符串生成对应数组的方法
Sep 22 PHP
php结合curl实现多线程抓取
Jul 09 PHP
PHP类的特性实例分析
Sep 28 PHP
php+ajax无刷新上传图片的实现方法
Dec 06 PHP
PHP错误处理函数register_shutdown_function使用示例
Jul 03 PHP
使用PHPStorm+XDebug搭建单步调试环境
Nov 19 PHP
php生成短网址/短链接原理和用法实例分析
May 29 PHP
PHP基于phpqrcode类生成二维码的方法示例详解
Aug 07 PHP
thinkphp5 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
PHP is_dir() 判断给定文件名是否是一个目录
2010/05/10 PHP
php中curl和file_get_content的区别
2014/05/10 PHP
Yii2超好用的日期和时间组件(值得收藏)
2016/05/05 PHP
jQuery getJSON 处理json数据的代码
2010/07/26 Javascript
jQuery:delegate中select()不起作用的解决方法(实例讲解)
2014/01/26 Javascript
JavaScript使用cookie记录临时访客信息的方法
2015/04/07 Javascript
判断数组的最佳方法(推荐)
2016/10/11 Javascript
ES6入门教程之let和const命令详解
2017/05/17 Javascript
简述jQuery Easyui一些用法
2017/08/01 jQuery
详解基于vue的移动web app页面缓存解决方案
2017/08/03 Javascript
浅谈vue-router2路由参数注意的问题
2017/11/08 Javascript
详解vue移动端日期选择组件
2018/02/22 Javascript
JavaScript:ES2019 的新特性(译)
2019/08/08 Javascript
BootStrap表单验证中的非Submit类型按钮点击时触发验证的坑
2019/09/05 Javascript
js获取 gif 的帧数的代码实例
2019/09/10 Javascript
vue移动端模态框(可传参)的实现
2019/11/20 Javascript
JS如何实现封装列表右滑动删除收藏按钮
2020/07/23 Javascript
python读写ini配置文件方法实例分析
2015/06/30 Python
python解析基于xml格式的日志文件
2017/02/25 Python
彻彻底底地理解Python中的编码问题
2018/10/15 Python
python的常见矩阵运算(小结)
2019/08/07 Python
Python流程控制 while循环实现解析
2019/09/02 Python
Pycharm中切换pytorch的环境和配置的教程详解
2020/03/13 Python
Django-imagekit的使用详解
2020/07/06 Python
Python离线安装各种库及pip的方法
2020/11/28 Python
CSS3制作ajax loader icon实现思路及代码
2013/08/25 HTML / CSS
Asics日本官网:鬼冢八喜郎创立的跑鞋运动品牌
2017/10/18 全球购物
印度服装购物网站:Limeroad
2018/09/26 全球购物
实习老师个人总结的自我评价
2013/09/28 职场文书
医院门卫岗位职责
2013/12/30 职场文书
初中政治教学反思
2014/01/17 职场文书
公休请假条
2014/04/11 职场文书
保留意见审计报告
2015/06/05 职场文书
优质服务标语口号
2015/12/26 职场文书
2021年国漫热度排行前十,完美世界上榜,第四是美国动画作品
2022/03/18 国漫
Moment的feature导致线上bug解决分析
2022/09/23 Javascript