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与已存在的Java应用程序集成
Oct 09 PHP
Windows 下的 PHP-PEAR 安装方法
Nov 20 PHP
php array_walk() 数组函数
Jul 12 PHP
php function用法如何递归及return和echo区别
Mar 07 PHP
PHP实现数组递归转义的方法
Aug 28 PHP
学习php设计模式 php实现桥梁模式(bridge)
Dec 07 PHP
[原创]PHP简单开启curl的方法(测试可行)
Jan 11 PHP
zen_cart实现支付前生成订单的方法
May 06 PHP
基于PHP实现用户注册登录功能
Oct 14 PHP
Yii CFileCache 获取不到值的原因分析
Feb 08 PHP
thinkPHP+ajax实现统计页面pv浏览量的方法
Mar 15 PHP
laravel请求参数校验方法
Oct 10 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统计字符串中中英文字符的个数
2013/06/23 PHP
php中注册器模式类用法实例分析
2015/11/03 PHP
php获取'/'传参的值简单方法
2017/07/13 PHP
PHP简单实现解析xml为数组的方法
2018/05/02 PHP
Yii框架日志记录Logging操作示例
2018/07/12 PHP
laravel 解决路由除了根目录其他都404的问题
2019/10/18 PHP
jquery-easyui关闭tab自动切换到前一个tab
2010/07/29 Javascript
jQuery UI Autocomplete 1.8.16 中文输入修正代码
2012/04/16 Javascript
JS倒计时代码汇总
2014/11/25 Javascript
jQuery实现仿百度帖吧头部固定导航效果
2015/08/07 Javascript
Jsonp 关键字详解及json和jsonp的区别,ajax和jsonp的区别
2015/12/30 Javascript
分享javascript计算时间差的示例代码
2020/03/19 Javascript
jQuery 获取多选框的值及多选框中文的函数
2016/05/16 Javascript
nodejs 终端打印进度条实例代码
2017/04/22 NodeJs
vue-router单页面路由
2017/06/17 Javascript
JavaScript使用prototype原型实现的封装继承多态示例
2018/08/31 Javascript
Vue中的基础过渡动画及实现原理解析
2018/12/04 Javascript
实现elementUI表单的全局验证的方法步骤
2019/04/29 Javascript
js实现点击选项置顶动画效果
2020/08/25 Javascript
Vue全局使用less样式,组件使用全局样式文件中定义的变量操作
2020/10/21 Javascript
对python中的xlsxwriter库简单分析
2018/05/04 Python
python实现简易内存监控
2018/06/21 Python
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
python 数据库查询返回list或tuple实例
2020/05/15 Python
Python通过队列来实现进程间通信的示例
2020/10/14 Python
美国时尚女装在线:Missguided
2016/12/03 全球购物
GUESS德国官网:美国牛仔服装品牌
2017/02/14 全球购物
开业庆典邀请函
2014/01/08 职场文书
大学军训感言1500字
2014/03/09 职场文书
旅行社各个岗位职责
2014/03/15 职场文书
企业党员一句话承诺
2014/05/30 职场文书
小学生校园广播稿
2014/09/28 职场文书
少先队工作总结2015
2015/05/13 职场文书
学校运动会加油词
2015/07/18 职场文书
CSS变量实现主题切换的方法
2021/06/23 HTML / CSS
Nginx内网单机反向代理的实现
2021/11/07 Servers