ryunosuke/polyfill-enum

模拟 php8.1 的 enum

v1.1.1 2024-07-05 01:45 UTC

This package is auto-updated.

Last update: 2024-09-05 02:10:59 UTC


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*。这些与原生完全兼容。

用法

请查看示例以获取详细信息

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 UnitEnumnew ReflectionEnum(),也可以无问题地使用
      • 还了解到 uopz 的 redefine 可以将对象存储到常量中,这对提高可用性有很大帮助。只要有这个,使用起来就可以接近 8.1 原生的水平了
  • 问题:功能很少吗?
    • 答案:我专注于 polyfill。如果添加不必要的便利功能,迁移就会变得困难
      • 仅提供类似 enum 的功能,以便在迁移到 8.1 时只需进行最小限度的更改,这是概念(最终目标是只更改定义部分)
      • 当然,有 __toString 或 name => value 数组的返回方法等很方便...

发布

遵循语义版本控制。

  • 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