ryunosuke / polyfill-enum
模拟 php8.1 的 enum
v1.1.1
2024-07-05 01:45 UTC
Requires
- php: >=8.0
Requires (Dev)
README
描述
此软件包模拟 php8.1 及以上版本的 enum 功能。
安装
{ "require": { "ryunosuke/polyfill-enum": "*" } }
示例
# Below are the same results
php80 demo/php80-polyfill.php
php81 demo/php81-builtin.php
规范
继承自 *Enum
的公共常量视为 enum 情况,情况通过方法调用获取。所有其他规范与原生 enum 相同。
*Enum
PureEnum
: 兼容原生 PureEnum (如enum Hoge {...}
)IntBackedEnum
: 兼容原生 IntBackedEnum (如enum Fuga: int {...}
)StringBackedEnum
: 兼容原生 StringBackedEnum (如enum Piyo: string {...}
)
此软件包还提供 ReflectionEnum*
。这些与原生完全兼容。
ReflectionEnum*
用法
请查看示例以获取详细信息
enum
php8.1 的 enum 如下所示
enum Suit1 { use Magicable; // explain later const SIMPLE_CONST = null; private const OTHER_CONST = null; case Hearts; case Diamonds; case Clubs; case Spades; } var_dump(count(Suit1::cases())); // int(4) enum Suit2: int { use Magicable; // explain later const SIMPLE_CONST = 0; const OTHER_CONST = ''; case Hearts = 1; case Diamonds = 2; case Clubs = 3; case Spades = 4; } var_dump(count(Suit2::cases())); // int(4) enum Suit3: string { use Magicable; // explain later const SIMPLE_CONST = ''; const OTHER_CONST = 0; case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } var_dump(count(Suit3::cases())); // int(4)
此软件包的 enum 如下所示
class Suit1 extends PureEnum { #[EnumCase(false)] const SIMPLE_CONST = null; // This is not a case (because EnumCase attribute). private const OTHER_CONST = null; // This is not a case (because it is not public). const Hearts = null; const Diamonds = null; const Clubs = null; const Spades = null; } var_dump(count(Suit1::cases())); // int(4) class Suit2 extends IntBackedEnum { #[EnumCase(false)] const SIMPLE_CONST = 0; // This is not a case (because EnumCase attribute). const OTHER_CONST = ''; // This is not a case (because it is not int). const Hearts = 1; const Diamonds = 2; const Clubs = 3; const Spades = 4; } var_dump(count(Suit2::cases())); // int(4) class Suit3 extends StringBackedEnum { #[EnumCase(false)] const SIMPLE_CONST = ''; // This is not a case (because EnumCase attribute). const OTHER_CONST = 0; // This is not a case (because it is not string). const Hearts = 'H'; const Diamonds = 'D'; const Clubs = 'C'; const Spades = 'S'; } var_dump(count(Suit3::cases())); // int(4)
enum 情况是常量...
- public
- 值匹配支持类型(Pure 为 null)
- 不是 EnumCase(false)
- 注意:EnumCase(true) 目前没有效果
mixin
定义了几个 trait,可以方便地按需使用。
- Methodable:提供魔术方法调用
__callStatic
:通过名称返回情况(例如Suit::Hearts()
)- 对于 php < 8.1 实际上需要
- Compatible:提供与 php8.1 原生 enum 的兼容性
- 禁用魔术方法(例如 clone、sleep 等)
- 如 enum 一样的断言(例如 final、无属性等)
- 其他
- Initializable:提供
initialize
- 这可以像 java 静态初始化器一样使用
注意
使用 8.1 的 polyfill 可能会部分不兼容。具体来说,enum_exists 的结果可能会改变,或者 UnitEnum 的 instanceof 可能会停止响应。这是由于内置的,因此无法避免(无法使内置的 enum_exists 响应醇醇类,并且 UnitEnum 的子类也不再是)。
在示例中
- 8.0 中使用 polyfill 的示例
- 8.1 中使用 polyfill 的示例
- 8.1 中使用内置的示例
请比较输出结果。
常见问题解答
- 问题:8.1 的原生不好吗?
- 答案:由于 rhel9 的 app stream 采用了 php8.0(10 年支持),因此预计 8.0 的绑定将持续一段时间(当然,7.4 仍在存活)
- 问题:有没有其他优秀的库?
- 答案:是的。但我不是想要“enum”,而是想要“php8.1 的 native enum 兼容”(如 UnitEnum 或 ReflectionEnum)
- 例如,即使依赖库中有
instanceof UnitEnum
或new ReflectionEnum()
,也可以无问题地使用 - 还了解到 uopz 的 redefine 可以将对象存储到常量中,这对提高可用性有很大帮助。只要有这个,使用起来就可以接近 8.1 原生的水平了
- 例如,即使依赖库中有
- 答案:是的。但我不是想要“enum”,而是想要“php8.1 的 native enum 兼容”(如 UnitEnum 或 ReflectionEnum)
- 问题:功能很少吗?
- 答案:我专注于 polyfill。如果添加不必要的便利功能,迁移就会变得困难
- 仅提供类似 enum 的功能,以便在迁移到 8.1 时只需进行最小限度的更改,这是概念(最终目标是只更改定义部分)
- 当然,有 __toString 或 name => value 数组的返回方法等很方便...
- 答案:我专注于 polyfill。如果添加不必要的便利功能,迁移就会变得困难
发布
遵循语义版本控制。
- https://semver.org
- 主要:更改规范(BC 断开连接)
- 次要:添加功能(无 BC 断开连接)
- 修补:修复错误(无 BC 断开连接)
1.1.1
- [merge] 1.0.2
1.1.0
- [*change] php>=8.0
1.0.2
- [fixbug] trait/interface 在读取时出现多重定义错误的不兼容
1.0.1
- [fixbug] 修正自动加载无限循环的问题
1.0.0
- 发布
许可证
MIT