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初学者的8点有效建议
Nov 20 PHP
php 缩略图实现函数代码
Jun 23 PHP
PHP+Ajax异步通讯实现用户名邮箱验证是否已注册( 2种方法实现)
Dec 28 PHP
php替换超长文本中的特殊字符的函数代码
May 22 PHP
PHP autoload与spl_autoload自动加载机制的深入理解
Jun 05 PHP
浅析php学习的路线图
Jul 10 PHP
PHP统一页面编码避免乱码问题
Apr 09 PHP
php实现的递归提成方案实例
Nov 14 PHP
PHP微信开发之查询城市天气
Jun 23 PHP
PHP使用mysqli操作MySQL数据库的简单方法
Feb 04 PHP
PHP实现的简单操作SQLite数据库类与用法示例
Jun 19 PHP
thinkphp5.0自定义验证规则使用方法
Nov 16 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
一个基于PDO的数据库操作类
2011/03/24 PHP
PHP提取字符串中的图片地址[正则表达式]
2011/11/12 PHP
深入探讨<br />和 \r\n两者有什么区别??
2013/06/05 PHP
PHP删除数组中空值的方法介绍
2014/04/14 PHP
PHP入门教程之字符串处理技巧总结(转换,过滤,解析,查找,截取,替换等)
2016/09/11 PHP
javascript简单事件处理和with用法介绍
2013/09/16 Javascript
鼠标移入移出事件改变图片的分辨率的两种方法
2013/12/17 Javascript
Javascript中3种实现继承的方法和代码实例
2014/08/12 Javascript
jquery 构造函数在表单提交过程中修改数据
2015/05/25 Javascript
javascript通过获取html标签属性class实现多选项卡的方法
2015/07/27 Javascript
Jquery实现简单的轮播效果(代码管用)
2016/03/14 Javascript
Bootstrap导航条鼠标悬停下拉菜单
2017/01/04 Javascript
微信分享调用jssdk实例
2017/06/08 Javascript
AngularJS 购物车全选/取消全选功能的实现方法
2017/08/14 Javascript
AngularJS2 与 D3.js集成实现自定义可视化的方法
2017/12/01 Javascript
vue鼠标移入添加class样式,鼠标移出去除样式(active)实现方法
2018/08/22 Javascript
简述vue状态管理模式之vuex
2018/08/29 Javascript
使用 vue 实例更好的监听事件及vue实例的方法
2019/04/22 Javascript
微信小程序实现点击空白隐藏的方法示例
2019/08/13 Javascript
JS代码实现页面切换效果
2021/01/10 Javascript
举例讲解Python的Tornado框架实现数据可视化的教程
2015/05/02 Python
python使用super()出现错误解决办法
2017/08/14 Python
利用python批量修改word文件名的方法示例
2017/10/17 Python
关于PyTorch 自动求导机制详解
2019/08/18 Python
python sleep和wait对比总结
2021/02/03 Python
中国领先的专业演出票务网:永乐票务
2016/08/29 全球购物
科颜氏印度官网:Kiehl’s印度
2021/02/20 全球购物
亚马逊意大利站点:Amazon.it
2020/12/31 全球购物
采购员岗位职责
2013/11/15 职场文书
房产转让协议书(2014版)
2014/09/30 职场文书
大一学生个人总结
2015/02/15 职场文书
军事理论课感想
2015/08/11 职场文书
教师旷工检讨书
2015/08/15 职场文书
2019学校运动会开幕词
2019/05/13 职场文书
Python基础之常用库常用方法整理
2021/04/30 Python
vue+spring boot实现校验码功能
2021/05/27 Vue.js