宿迁腾云网络网站建设公司

腾云网络 八年经验专注网站建设
  • 首页
  • 服务项目
    • 网站建设
    • 微信小程序
    • APP开发
    • SEO优化
  • 建站费用
  • 成功案例
    • 网站建设案例
    • 小程序案例
    • APP开发案例
    • SEO优化案例
  • 行业动态
    • 网站建设
    • SEO优化
    • 技术日志
  • 联系我们
    • 关于我们
首页 > 行业动态 > 技术日志 > 腾云网络教你如何处理 PHP 代码中的枚举类型 Enum 的

腾云网络教你如何处理 PHP 代码中的枚举类型 Enum 的

2019-10-12

本文旨在提供一些更好的理解什么是枚举,什么时候使用它们以及如何在php中使用它们.

我们在某些时候使用了常量来定义代码中的一些常数值.他们被用来避免 魔法值 .用一个象征性的名字代替一些 魔法值 ,我们可以给它一些意义.然后我们在代码中引用这个符号名称.因为我们定义了一次并使用了很多次,所以搜索它并稍后重命名或更改一个值会更容易.

这就是为什么看到类似于下面的代码并不罕见.

<?php
class User {
    const GENDER_MALE = 0;
    const GENDER_FEMALE = 1;
    const STATUS_INACTIVE = 0;
    const STATUS_ACTIVE = 1;
}

以上常量表示了两组属性,GEDNER_* 和 STATUS_*。他们表示一组性别和一组用户状态。每一组都是一个 枚举 。枚举是一组元素(也叫做成员)的集合,每一个枚举都定义了一种新类型。这个类型,和它的值一样,可以包含任意属于该枚举的元素。

在上面的例子中,枚举借助于常量,每一个常量的值都是一个成员。注意,这样做的话,我们只能在常量包含的类型中取值。因此,我们在写这些值的时候不会有类型提示,不知道详细的枚举类型。

来看一个简短的例子, 但我们假定例子中有更多的代码

<?php
interface UserFactory {
    public function create(
        string $email,
        int $gender,
        int $status
    ): User;
}
$factory->create(
    $email,
    User::STATUS_ACTIVE,
    User::GENDER_FEMALE
);

第一眼看上去代码很好,但是他只是碰巧正确运行了!因为两个不同的枚举成员实际上是同一个值,调用create方法成功,是因为这最后两个参数被互换了不影响结果。尽管我们检查方法接受的值是否有效,运行界面也不会警告我们,测试也会通过。有人能正确的发现这些bug,但是它也很可能被忽视掉。之后一些情况,比如合并冲突的时候,如果它的值改变了,它可能会引起系统异常。

如果使用标量类型,我们会受限于这种类型,无法辨别这两个值是是不是属于两个不同的枚举。

另一个问题是这个代码描述的的不是很好。想象一下 create 方法没有引用常量。 $gender 被别人看作为一个枚举元素将是有多么困难?看这些元素在哪里被定义又有多么困难?我们之后将会阅读那些代码,因此我们应该尽可能是让代码易于阅读以及和通过。

我们可以做得更好吗?Sure!这个方法就是是使用类实例作为枚举元素,类本身定义了一个新的类型。直到PHP 7,我们可以安装 SPL类 PECL扩展并且使用 SplEnum 。

<?php
class YesNo extends \SplEnum
{
    const __default =  self::YES;
    const NO = 0;
    const YES = 1;
}
$no = new YesNo(YesNo::NO);
var_dump($no == YesNo::NO); //true
var_dump(new YesNo(YesNo::NO) == YesNo::NO); //true

我们扩展 SplEnum 并且定义用于创建枚举元素的常量。枚举元素是我们手动构造的对象,在这种情况下是常量值本身。我们可以将整型与对象进行比较,这可能很奇怪。另外,正如文档所述,这是一个仿真的枚举。PHP本身并不支持枚举类型,所以我们在这里探讨的所有内容都是仿真的。

我们用这种方法得到了什么?我们可以输入提示我们的参数,并让PHP引擎在发生错误时提醒我们。我们还可以在枚举类中包含一些逻辑,并使用 switch 语句来模拟多态行为。

但也有一些缺点. 例如, 在大多数情况下, 有些你可以用枚举元素而不能用标识检查. 这不是不可能的,我们不得不非常小心. 由于我们手动创建枚举成员, 所以许多成员应该是同一个成员, 但这一点手动很难确定.

利用 SplEnum 我们解决枚举类型问题, 但是当我们用标识检查的时候不得不非常小心. 我们需要一个方法限制可以创建的多个元素, 例如  multiton (multiple  singleton objects ).

现在我们将看到由 Java Enum 启发并实现 multiton 的两个不同的库.

第一个是 eloquent/enumeration . 它为每个元素创建一个定义类的实例. 请注意, 没有我们的帮助, 枚举的用户仿真永远不能保证一个枚举实例, 因为我们限制它的每一步都有一个方法去避免.

这个库可以让我们用错误的方式去尝试, 例如用反射创建一个实例, 在这一点上我们可以问我们自己是否做了正确的事. 它也可以在代码的评审过程中有所帮助,因为这样的实现可以定义几个应该被遵循的规则. 如果这些规则比较简单很容易发现代码中存在的问题.

让我们看些实例.

<?php
final class YesNo extends \Eloquent\Enumeration\AbstractEnumeration {
    const NO = 0;
    const YES = 1;
}
var_dump(YesNo::YES()->key()); // YES

我们定义了一个继承 \Eloquent\Enumeration\AbstractEnumeration 的新类  YesNo . 接下来我们定义一个定义元素名和创建表现这些元素的对象的库的常量.

还有一些情况我们需要谨记,用 serialize / deserialize 在其中创建自定义对象 .

我们可以在GitHub页面上找到更多的例子和很完善的文档。

我们要展示的第二个库是 zlikavac32/php-enum . 与  eloquent/enumeration 不同,这个库面向允许真正的多态行为的抽象类。所以,我们可以用每个方法都定义一个枚举元素来实现,而不是使用 switch 的方法。通过严格的规则来定义枚举,也可以相当可靠地确保每个元素只有一个实例。

这个库面向抽象类,以便将每个成员的许多实例限制为一个。这个想法是,每个枚举必须被定义为抽象的,并枚举它的元素。请注意,你可以通过扩展类,然后构造一个元素来滥用,但是如果你这么用了,这些是会在代码审查过程中标红的。

对于抽象类,我们知道我们不会意外地有一个枚举的新元素,因为它需要具体的实现。通过遵循在enum本身中保持这些具体实现的规则,我们可以很容易地发现滥用。 匿名类 在这里很有用。

库强制抽象枚举类,但不能强制创建有效的元素。这是这个库的用户的责任。图书馆照顾其余的。

让我们看一个简单的例子。

<?php
/**
 * @method static YesNo YES
 * @method static YesNo NO
 */
abstract class YesNo extends \Zlikavac32\Enum\Enum
{
    protected static function enumerate(): array
    {
        return [
            'YES', 'NO'
        ];
    }
}
var_dump(YesNo::YES()->name()); // YES

PHPDoc注释定义了返回枚举元素的现有静态方法。这有助于搜索和重构代码。接下来,我们将枚举 YesNo 定义为抽象,并扩展 \Zlikavac32\Enum\Enum 并定义一个静态方法 enumerate 。然后,在 enumerate 方法中,我们列出将被用来表示它们的元素名称。

刚刚我们提到了多态行为,那么为什么我们会使用它呢?当我们试图限制同一个枚举元素的多个实例时会发生一件事,那就是我们不能有循环引用。让我们想象一下,我们想拥有由 NORTH , SOUTH , EAST 和 WEST 组成的 WorldSide 枚举。我们还想有一个方法 opposite():WorldSide ,它返回代表相反的元素。

如果我们试图通过构造函数注入相反元素,在某一时刻,我们获得一个循环引用,这意味着,我们需要相同元素的第二个实例。为了返回一个有效的相反世界,我们不得不用一个 代理对象 或者 switch 语句破解。

随着多态行为,我们能做的就是让我们看到我们可定义我们需要的 WorldSide 枚举。

<?php
/**
 * @method static WorldSide NORTH
 * @method static WorldSide SOUTH
 * @method static WorldSide EAST
 * @method static WorldSide WEST
 */
abstract class WorldSide extends \Zlikavac32\Enum\Enum
{
    protected static function enumerate(): array
    {
        return [
            'NORTH' => new class extends WorldSide {
                public function opposite(): WorldSide {
                    return WorldSide::SOUTH();
                }
            },
            'SOUTH' => new class extends WorldSide {
                public function opposite(): WorldSide {
                    return WorldSide::NORTH();
                }
            },
            'EAST' => new class extends WorldSide {
                public function opposite(): WorldSide {
                    return WorldSide::WEST();
                }
            },
            'WEST' => new class extends WorldSide {
                public function opposite(): WorldSide {
                    return WorldSide::EAST();
                }
            }
        ];
    }
    abstract public function opposite(): WorldSide;
}
foreach (WorldSide::iterator() as $worldSide) {
    var_dump(sprintf(
        'Opposite of %s is %s',
        (string) $worldSide,
        (string) $worldSide->opposite()
    ));
}

在 enumerate 方法,我们提供了每一个枚举元素的实现。数组是用枚举元素名称来索引的。当手动的创建元素,我们定义我们元素名称作为数据的键。

我们可以用 WorldSide::iterator() 获取枚举元素的顺序迭代器,来定义和遍历他们。每一个枚举元素都有一个默认的  __toString(): string 实现返回元素的名称。

每个枚举元素返回其相反的元素。

回顾一下,常量不是枚举,枚举不是常量。每个枚举定义一个类型。如果我们有一些常数的值对我们很重要,但名字没有,我们应该坚持常数。如果我们有一些常量的价值对我们无关紧要,但是与同一群体中的其他所有人有所不同则是重要的,请使用枚举

枚举为代码提供了更多的上下文,也可以将某些检查委托给引擎本身。如果PHP有一个本地的枚举支持,这将是非常好的。语法更改可以使代码更具可读性。引擎可以为我们执行检查,并执行一些不能从用户区执行的规则。


Tag:
网站制作公众号

宿迁腾云网络网站建设公司 | 网站开发 | 网站制作 | 网站优化

咨询电话:13160355545

上一篇

返回栏目

下一篇

免责声明:本站所有文章和图片均来自用户分享和网络收集,文章和图片版权归原作者及原出处所有,仅供学习与参考,请勿用于商业用途,如果损害了您的权利,请联系网站客服处理。

热推

  • php上传图片代码编辑从基础到内核,分享PHP的方方面面实现思路!php上传视频文件代码
  • php开源b2c商城系统 商城系统开发需要做哪些准备工作?前期准备少php开源商城框架
  • Java的微信开发中使用XML格式和JSON格式数据的详解及实例
  • 开源php即时通讯系统云原生批流融合数据平台宣布获得2300万美元A轮融资深喉咙php免费开源企业建站系统
  • php是什么文件格式?如何打开可以使用编辑器?
  • 网站后台管理系统php【开源精选】后台管理UI基于最新版本的第三方插件php中网站不同模板后台逻辑代码怎么管理
  • 使用php代码格式化工具()需在命令行下进行
  • 兼职开发者论坛php“腾云网络”每天赚100-200元php开发工程师
  • php文件是一种不能轻易打开的文件,这种方式更简单
  • 如何实现两台数据库数据的同步吗?(56云小编一起)

相关

标签

seo(1191) 市场营销(661) 网站制作(573) 网站建设(567) 搜索引擎(553) 网站(482) PHP(363) 编程语言(346) 建站(294) 关键词排名优化(267) 网站建设公司(245) 优化(216) seo排名(207) 域名(190) 软件(171) 网站优化(150) 搜索引擎优化(150) 外链(141) 科技(136) 网站关键词(124) 网站排名优化(123) 域名服务器(120) 网站排名(109) 时政(103) 排名优化(95) 搜索引擎收录(93) 网站设计(93) 电子商务(88) 引擎(86) 移动互联网(85) 开发框架(79) 开发(75) 网站服务器(74) 框架(68) 前端开发(68) 网站建设方案(66) 网站分析(66) 关键(64) 流量(63) 源码(62) 百度优化(62) 网站权重(61) 开放源代码(59) seo培训(53) php框架(51) 网页设计(51) 百度(51) 网站建设知识(50) 谷歌(50) 大数据(50)
宿迁腾云网络网站建设公司
网站建设
  • 私人定制
  • 标准模板建站
  • 经济模板建站
精品模板

宿迁腾云网络网站建设公司

联系电话:13160355545

公司地址:江苏省宿迁市丽景湾华庭北门都市花园公寓9楼907

联系邮箱:admin@tyweb.net

全国分站
  • 北京
  • 广东
  • 东莞 广州 中山 深圳 惠州 江门 珠海 汕头 佛山 湛江 河源 肇庆 潮州 清远 韶关 揭阳 阳江 云浮 茂名 梅州 汕尾
  • 山东
  • 济南 青岛 临沂 济宁 菏泽 烟台 泰安 淄博 潍坊 日照 威海 滨州 东营 聊城 德州 莱芜 枣庄
  • 江苏
  • 苏州 徐州 盐城 无锡 南京 南通 连云港 常州 扬州 镇江 淮安 泰州 宿迁
  • 河南
  • 郑州 南阳 新乡 安阳 洛阳 信阳 平顶山 周口 商丘 开封 焦作 驻马店 濮阳 三门峡 漯河 许昌 鹤壁 济源
  • 上海
  • 河北
  • 石家庄 唐山 保定 邯郸 邢台 沧州 秦皇岛 张家口 衡水 廊坊 承德
  • 浙江
  • 温州 宁波 杭州 台州 嘉兴 金华 湖州 绍兴 舟山 丽水 衢州
  • 陕西
  • 西安 咸阳 宝鸡 汉中 渭南 安康 榆林 商洛 延安 铜川
  • 湖南
  • 长沙 邵阳 常德 衡阳 株洲 湘潭 永州 岳阳 怀化 郴州 娄底 益阳 张家界 湘西
  • 重庆
  • 福建
  • 漳州 泉州 厦门 福州 莆田 宁德 三明 南平 龙岩
  • 天津
  • 云南
  • 昆明 红河 大理 文山 德宏 曲靖 昭通 楚雄 保山 玉溪 丽江 临沧 思茅 西双版纳 怒江 迪庆
  • 四川
  • 成都 绵阳 广元 达州 南充 德阳 广安 阿坝 巴中 遂宁 内江 凉山 攀枝花 乐山 自贡 泸州 雅安 宜宾 资阳 眉山 甘孜
  • 广西
  • 贵港 玉林 北海 南宁 柳州 桂林 梧州 钦州 来宾 河池 百色 贺州 崇左 防城港
  • 安徽
  • 芜湖 合肥 六安 宿州 阜阳 安庆 马鞍山 蚌埠 淮北 淮南 宣城 黄山 铜陵 亳州 池州 巢湖 滁州
  • 海南
  • 三亚 海口 琼海 文昌 东方
  • 江西
  • 南昌 赣州 上饶 吉安 九江 新余 抚州 宜春 景德镇 萍乡 鹰潭
  • 湖北
  • 武汉 宜昌 襄樊 荆州 恩施 孝感 黄冈 十堰 咸宁 黄石 仙桃 随州 天门 荆门 潜江 鄂州 神农架
  • 山西
  • 太原 大同 运城 长治 晋城 忻州 临汾 吕梁 晋中 阳泉 朔州
  • 辽宁
  • 大连 沈阳 丹东 辽阳 葫芦岛 锦州 朝阳 营口 鞍山 抚顺 阜新 本溪 盘锦 铁岭
  • 黑龙江
  • 齐齐哈尔 哈尔滨 大庆 佳木斯 双鸭山 牡丹江 鸡西 黑河 绥化 鹤岗 伊春 大兴安岭 七台河
  • 内蒙古
  • 赤峰 包头 通辽 呼和浩特 乌海 鄂尔多斯 呼伦贝尔
  • 贵州
  • 贵阳 黔东 黔南 遵义 黔西 毕节 铜仁 安顺 六盘水
  • 甘肃
  • 兰州 天水 庆阳 武威 酒泉 张掖 陇南 白银 定西 平凉 嘉峪关 临夏 金昌 甘南
  • 青海
  • 西宁 海西 海东 海北 果洛 玉树 黄南
  • 新疆
  • 乌鲁木齐 伊犁 昌吉 石河子 哈密
  • 西藏
  • 拉萨 山南 林芝 日喀则
  • 吉林
  • 长春 白山 白城 延边 松原 辽源 通化 四平
  • 宁夏
  • 银川 吴忠 中卫 石嘴山 固原
SiteMap
网站地图
TAG标签
Copyright © 2017-2025 TYWEB.NET 宿迁腾云网络科技有限公司 ALL RIGHTS RESERVED.   苏ICP备17033535号-1

热门搜索

下载 2025 2026 2024 请输入关健词 货源 货货源 虚拟
  • 客服

    在线客服

  • 电话

    13160355545

  • 微信

精品模板
建站费用
成功案例
联系我们