eclipxe/enum

基于 Brent Roose 的 enum 理念 https://stitcher.io/blog/php-enums

v0.2.6 2021-06-18 02:12 UTC

This package is auto-updated.

Last update: 2024-09-03 14:32:55 UTC


README

Source Code Packagist PHP Version Support Latest Version Software License Build Status Scrutinizer Coverage Status Total Downloads

基于 Brent Roose 的 enum 理念 https://stitcher.io/blog/php-enums

阅读了关于 PHP Enums from Brent Roose 的文章,并回顾了在 spatie/enum 上所做的实现,我觉得它超出了我的预期。也许 spatie/enum 版本 1.0 更接近我所需要的。

因此,我创建了这个关于相同概念的无框架实现库。

截至 PHP 8.1,枚举是语言的一部分,这意味着这个库将不再需要。阅读 PHP 文档 https://php.ac.cn/manual/en/language.enumerations.php 并适应您的代码。PHP 枚举和此库中的对象之间的一大区别是,本机 PHP 枚举不能使用魔术方法 __toString(它们不是 Stringable),而此库中的枚举是。

安装

使用 composer,使用以下命令安装

composer require eclipxe/enum

使用方法

其他语言中的 Enum 在代码中是 TEXT,在值中是 INTEGER

有两个有意义的信息:索引integer)和string)。

此库提供了一个 Eclipxe\Enum 抽象类 供扩展。值是该方法的名称,如声明在 docblock 中。索引是 docblock 中的位置(从零开始)。

值一个接一个地注册,采用重写的值或方法的名称。

索引一个接一个地注册,采用重写的索引或已注册的最大值加 1。

枚举示例

<?php
/**
 * This is a common use case enum sample
 * source: tests/Fixtures/Stages.php
 *
 * @method static self created()
 * @method static self published()
 * @method static self reviewed()
 * @method static self purged()
 *
 * @method bool isCreated()
 * @method bool isPublished()
 * @method bool isReviewed()
 * @method bool isPurged()
 */
final class Stages extends Eclipxe\Enum\Enum
{
}

实例创建

您可以使用带值构造函数、带索引构造函数或静态方法名称从值创建新实例。

<?php
use Eclipxe\Enum\Tests\Fixtures\Stages;

// create from value
$purged = new Stages('purged');
 
// create from index
$purged = new Stages(3);

// create from an object that can be converted to string and contains the value
$other = new Stages($purged);

// create from static method
$purged = Stages::purged();

// create from static method is not case-sensitive as methods are not
$purged = Stages::{'PURGED'}();

// throws a BadMethodCallException because foobar is not part of the enum
$purged = Stages::{'FOOBAR'}();

列出所有选项

Enum 暴露的唯一静态方法是 Enum::toArray(): array,它将注册的可能值的列表导出为索引和值的数组。

<?php
use Eclipxe\Enum\Tests\Fixtures\Stages;

var_export(Stages::toArray());
/*
[
    0 => 'created',
    1 => 'published',
    2 => 'reviewed',
    3 => 'purged',
] 
*/

检查实例是否为特定类型

使用方法 is<name>() 将其与特定值进行比较。

您必须在 docblock 中定义这些方法,以便您的 IDE 或代码分析器检测您正在执行的操作。

<?php
use Eclipxe\Enum\Tests\Fixtures\Stages;

$stage = Stages::purged();

$stage->isPurged(); // true
$stage->isPublished(); // false

$stage->{'isSomethingElse'}(); // false, even when SomethingElse is not defined
$stage->{'SomethingElse'}(); // throw BadMethodCallException

或使用弱比较(相等,非身份)

<?php
use Eclipxe\Enum\Tests\Fixtures\Stages;

$stage = Stages::purged();
var_export($stage === Stages::purged()); // false, is not the same identity
var_export($stage == Stages::purged()); // true
var_export($stage == Stages::published()); // false
var_export($stage->value() === Stages::purged()->value()); // true (compare using value)
var_export($stage->index() === Stages::purged()->index()); // true (compare using index)

重写值或索引

您可以通过重写方法 overrideValues()overrideIndices() 来重写值或索引。

规则

  • 返回 array 键必须是 docblock 部分中定义的方法的名称(区分大小写)。
  • 如果重写的值是 null,则不会重写。
  • 当重写值时,如果之前存在值,则将抛出 ValueOverrideException
  • 当重写索引时,如果之前存在值,则将抛出 IndexOverrideException
<?php
/**
 * This is an enum case where names and values are overridden
 *
 * @method static self monday()
 * @method static self tuesday()
 * @method static self wednesday()
 * @method static self thursday()
 * @method static self friday()
 * @method static self saturday()
 * @method static self sunday()
 */
final class WeekDays extends \Eclipxe\Enum\Enum
{
    protected static function overrideValues(): array
    {
        return [
            'monday' => 'Monday',
            'tuesday' => 'Tuesday',
            'wednesday' => 'Wednesday',
            'thursday' => 'Thursday',
            'friday' => 'Friday',
            'saturday' => 'Saturday',
            'sunday' => 'Sunday',
        ];
    }

    protected static function overrideIndices(): array
    {
        return [
            'monday' => 1,
        ];
    }
}

这将定义这些 array<index, value>,使用静态方法 WeekDays::toArray() 获取

[
    1 => 'Monday',
    2 => 'Tuesday',
    3 => 'Wednesday',
    4 => 'Thursday',
    5 => 'Friday',
    6 => 'Saturday',
    7 => 'Sunday',
];

请记住,枚举创建取决于注册的值和索引,如果使用了无效的值或索引,则会抛出异常

<?php
use Eclipxe\Enum\Tests\Fixtures\WeekDays;

new WeekDays(0); // throws IndexNotFoundException
new WeekDays(1); // WeekDays {value: 'Monday', index: 1}

new WeekDays('sunday'); // throws ValueNotFoundException (it is case-sensitive)
new WeekDays('Sunday'); // WeekDays {value: 'Sunday', index: 7}

扩展

当创建扩展其他枚举的枚举时,父枚举在索引和值方面具有优先级。您不能覆盖前一个类中的索引或值。

我建议您将您的枚举类声明为 final 以禁用扩展。

如果使用类扩展,不要使用@method static self name()语法,而是使用@method static static name()语法,以便帮助分析工具。

请参阅以下示例:tests/Fixtures/ColorsBasic.phptests/Fixtures/ColorsExtended.phptests/Fixtures/ColorsExtendedWithBlackAndWhite.php

异常

由本包抛出的异常实现了空接口Eclipxe\Enum\Exceptions\EnumExceptionInterface

PHP 支持

此库至少与PHP 支持版本兼容,并具有活跃的支持。请尽量使用 PHP 的全部潜力。

我们遵循语义化版本控制。在主版本上,我们不会引入任何向后不兼容的更改。

内部类(使用@internal注解)不属于此协议,因为它们必须仅存在于本项目内部。请不要在您的项目中使用它们。

贡献

欢迎贡献!请阅读CONTRIBUTING以获取详细信息,并别忘了查看TODOCHANGELOG文件。

版权和许可

eclipxe/enum库版权所有© Carlos C Soto,许可使用MIT许可证(MIT)。请参阅LICENSE获取更多信息。