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 相关文章推荐
pw的一个放后门的方法分析
Oct 08 PHP
php 保留小数点
Apr 21 PHP
php is_file()和is_dir()用于遍历目录时用法注意事项
Mar 02 PHP
域名和cookie问题(域名后缀)
Oct 10 PHP
php 模拟get_headers函数的代码示例
Apr 27 PHP
深入apache配置文件httpd.conf的部分参数说明
Jun 28 PHP
PHP生成二维码的两个方法和实例
Jul 01 PHP
分享一则PHP定义函数代码
Feb 26 PHP
php读取csc文件并输出
May 21 PHP
利用PHP生成CSV文件简单示例
Dec 21 PHP
使用PHP+MySql+Ajax+jQuery实现省市区三级联动功能示例
Sep 15 PHP
关于PHP数组迭代器的使用方法实例
Nov 17 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
浅析Mysql 数据回滚错误的解决方法
2013/08/05 PHP
php中生成随机密码的自定义函数代码
2013/10/21 PHP
Yii中使用PHPExcel导出Excel的方法
2014/12/26 PHP
php采集中国代理服务器网的方法
2015/06/16 PHP
分享微信扫码支付开发遇到问题及解决方案-附Ecshop微信支付插件
2015/08/23 PHP
php 使用curl模拟登录人人(校内)网的简单实例
2016/06/06 PHP
PHP封装的分页类与简单用法示例
2019/02/25 PHP
PHP架构及原理知识点详解
2019/12/22 PHP
Prototype1.6 JS 官方下载地址
2007/11/30 Javascript
JQuery将文本转化成JSON对象需要注意的问题
2011/05/09 Javascript
JS对象与JSON格式数据相互转换
2012/02/20 Javascript
利用jquery写的左右轮播图特效
2014/02/12 Javascript
纯js实现遮罩层效果原理分析
2014/05/27 Javascript
JS实现的生成随机数的4个函数分享
2015/02/11 Javascript
javascript下拉列表中显示树形菜单的实现方法
2015/11/17 Javascript
JS触发服务器控件的单击事件(详解)
2016/08/06 Javascript
提高Web性能的前端优化技巧总结
2017/02/27 Javascript
Angular.JS内置服务$http对数据库的增删改使用教程
2017/05/07 Javascript
BootStrap Table 后台数据绑定、特殊列处理、排序功能
2017/05/27 Javascript
原生JS封装animate运动框架的实例
2017/10/12 Javascript
Vue父子组件双向绑定传值的实现方法
2018/07/31 Javascript
详解如何用VUE写一个多用模态框组件模版
2018/09/27 Javascript
详解如何webpack使用DllPlugin
2018/09/30 Javascript
JS使用栈判断给定字符串是否是回文算法示例
2019/03/04 Javascript
[49:18]2018DOTA2亚洲邀请赛 3.31 小组赛 A组 OG vs TNC
2018/04/01 DOTA
Python实现XML文件解析的示例代码
2018/02/05 Python
python3.6的venv模块使用详解
2018/08/01 Python
python监控进程状态,记录重启时间及进程号的实例
2019/07/15 Python
详解Python中打乱列表顺序random.shuffle()的使用方法
2019/11/11 Python
用html5实现语音搜索框的方法
2014/03/18 HTML / CSS
阿根廷旅游网站:almundo阿根廷
2018/02/12 全球购物
沃尔玛加拿大:Walmart.ca
2020/03/02 全球购物
大学生学习2014全国两会心得体会
2014/03/13 职场文书
心理健康活动总结
2014/04/30 职场文书
2014年收银工作总结
2014/11/13 职场文书
社交电商模式的兴起:这些新的商机千万别错过
2019/07/26 职场文书