divengine / enum
Div PHP 枚举解决方案
Requires
- php: >=5.0.0
This package is auto-updated.
Last update: 2024-09-23 04:25:47 UTC
README
这是一个使用类和类型提示的 PHP 枚举解决方案。你也可以构建枚举的税onomies!
枚举类型,简称 "enum",是一种用于对命名值进行分类的数据类型。枚举可以用来代替硬编码的字符串,以结构化和类型化的方式表示,例如博客文章的状态。
2019 年 7 月,我写了一个 gist 来寻找这个解决方案。
https://gist.github.com/rafageist/aef9825b7c935cdeb0c6187a2d363909/revisions
然后我把 gist 转换成了真实项目。 https://www.phpclasses.org/package/11366-PHP-Implement-enumerated-values-using-classes.html
问题
在 8.1 之前,PHP 没有原生的枚举类型,只有一个非常基础的 SPL 实现 (https://php.ac.cn/manual/en/class.splenum.php),但这真的不够用。一些解决方案使用常量,但并没有解决问题。如何验证 HOT 或 COLD?
从 8.1 开始,PHP 有了一个枚举实现 (https://php.ac.cn/manual/en/language.types.enumerations.php)。
现在你可以结合 PHP 的新功能来使用这个解决方案。
<?php const HOT = 1; const COLD = 2; const FIRE = 1; const ICE = 2; function doSomething(int $temperature) { /* ... */} doSomething(FIRE);
有一个流行的包叫做 myclabs/php-enum。它真的很棒,但有一个问题,因为我们失去了静态分析的好处,比如自动完成和重构。
解决方案
使用 PHP!
类 divengine\enum 可以帮助你,但请记住:这个库最重要的解决方案是它的概念。
使用这个类,你可以解决以下问题
- 具有不同名称和相等值的常量可以作为函数参数使用
- 失去静态分析的好处,如自动完成和重构
- 在使用文档块类型提示解决第二个问题时,维护重复的代码
我们需要在 PHP 中有内置的枚举!但,现在,这是一个解决方案。
安装
Composer
composer require divengine\enum;
手动
克隆仓库
git clone https://github.com/divengine/enum
包含库
include "/path/to/divengine/enum/src/folder/enum.php";
示例
首先,定义你的枚举。你可以构建一个税onomies!
Enums.php
<?php namespace MyEnums; use divengine\enum; class Temperature extends enum {/* Father of all types of temperatures */} class ExtremeTemperature extends Temperature {/* Father of all types of extreme temperatures */} class FIRE extends ExtremeTemperature {} class ICE extends ExtremeTemperature {} class NormalTemperature extends Temperature {/* Father of all types of normal temperatures */} class HOT extends NormalTemperature {} class COOL extends NormalTemperature {} class COLD extends NormalTemperature {}
其次,使用你的枚举
<?php use MyEnums; // Constants are good tricks, but optional const COOL = COOL::class; class AllTemperatures { const COOL = COOL::class; // maybe better const HOT = 'Enums\\HOT'; // ugly !!! //... } // Define some function with type hinting function WhatShouldIdo(Temperature $temperature) { switch (true) { case $temperature instanceof ExtremeTemperature: switch (true) { case $temperature instanceof FIRE: return "Call the fire department"; case $temperature instanceof ICE: return "Warm up"; } break; case $temperature instanceof NormalTemperature: switch ($temperature) { case HOT::class: // compare using classname return "Drink a beer :D"; case COOL or AllTemperatures::COOL: // compare using constants return "Just go away !"; case 'Enums\\COLD': // compare using string, ugly !!! return "Wear a coat"; } break; } return "I don't know"; } // Call to function with a instance of any Temperature echo WhatShouldIdo(new HOT()) . PHP_EOL;
你喜欢 Java 编程语言吗?
实际上你可以使用枚举进行开关,但你不能在 Java 7 之前使用字符串进行开关。你可以考虑使用 Java 枚举的多态方法调度而不是显式的 switch。请注意,枚举在 Java 中是对象,而不是像 C/C++ 中的 int 的符号。你可以在枚举类型上有一个方法,然后而不是写一个 switch,只需调用该方法 - 一行代码:完成!
public enum Temperature { HOT { @Override public void whatShouldIdo() { System.out.println("Drink a bear!"); } }, COLD { @Override public void whatShouldIdo() { System.out.println("Wear a coat!"); } }; public abstract void whatShouldIdo(); } // ... void aMethodSomewhere(final Temperature temperature) { doSomeStuff(); temperature.whatShouldIdo(); // here is where the switch would be, now it's one line of code! doSomeOtherStuff(); }
这种方法的一个好处是,你可以避免某些类型的错误。你不会错过一个 switch case(你可以为特定的常量错误地实现一个方法,但没有什么可以完全防止这种情况发生!)。没有 switch "default" 要担心。此外,我见过将枚举常量放入数组并将索引放入数组的代码 - 这打开了数组索引越界的异常的可能性 - 只需使用枚举!Java 枚举非常非常强大。了解有关它们的全部内容,以有效地使用它们。
此外,如果您有多个枚举常量,它们对某个特定方法具有相同的行为(例如星期几,周末的行为相同,以及星期二到星期四的工作日也具有相同的行为),您可以将这些共享代码简单地聚集在一个不会被每个常量(final protected)覆盖的枚举方法中,然后从适当的方法中调用该方法。因此,添加 "final protected void commonMethod() { ... }",然后在每个常量的 method() 方法的实现中只需调用 commonMethod()。
那么关于PHP呢?这是一个类似的解决方案...
<?php abstract class Temperature extends divengine\enum { public function whatShouldIdo() {} } class HOT extends Temperature { public function whatShouldIdo() { echo "Drink a bear!"; } } class COLD extends Temperature { public function whatShouldIdo() { echo "Wear a coat!"; } } // .... function someStuff(Temperature $t) { $t->whatShouldIdo(); } someStuff( new HOT() );
祝您玩得开心!
文档:[https://divengine.org](https://divengine.org) (外部链接,不跟随,不索引,不重新加载,非用户生成内容)
--
@rafageist
工程师 Rafa Rodriguez