archtechx/enums

使PHP枚举更加可爱的小助手。

v1.1.0 2024-07-15 14:28 UTC

This package is auto-updated.

Last update: 2024-09-15 14:53:14 UTC


README

PHP枚举辅助工具集合。

您可以在Twitter上了解更多关于原始想法的信息。

安装

需要PHP 8.1+。

composer require archtechx/enums

使用

可调用案例

此辅助工具允许您通过“调用”来获取支持枚举的值或纯枚举的名称——无论是静态的(MyEnum::FOO()而不是MyEnum::FOO),还是作为实例($enum())。

这样,您可以将枚举用作数组键

'statuses' => [
    TaskStatus::INCOMPLETE() => ['some configuration'],
    TaskStatus::COMPLETED() => ['some configuration'],
],

或访问任何其他用例的底层原始数据

public function updateStatus(int $status): void;

$task->updateStatus(TaskStatus::COMPLETED());

主要观点:这一切都不需要将->value附加到所有内容上。

这种方法还有相当的IDE支持。您在输入时获得自动建议,然后只需附加()

MyEnum::FOO; // => MyEnum instance
MyEnum::FOO(); // => 1

在您的枚举上应用特征

use ArchTech\Enums\InvokableCases;

enum TaskStatus: int
{
    use InvokableCases;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use InvokableCases;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}

使用静态调用以获取原始值

TaskStatus::INCOMPLETE(); // 0
TaskStatus::COMPLETED(); // 1
TaskStatus::CANCELED(); // 2
Role::ADMINISTRATOR(); // 'ADMINISTRATOR'
Role::SUBSCRIBER(); // 'SUBSCRIBER'
Role::GUEST(); // 'GUEST'

调用实例以获取原始值

public function updateStatus(TaskStatus $status, Role $role)
{
    $this->record->setStatus($status(), $role());
}

名称

此辅助工具返回枚举中案例的名称列表。

在您的枚举上应用特征

use ArchTech\Enums\Names;

enum TaskStatus: int
{
    use Names;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use Names;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}

使用names()方法

TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED']
Role::names(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']

此辅助工具返回支持枚举的案例列表,或纯枚举的案例名称列表(使此函数与纯枚举的::names()功能等效)

在您的枚举上应用特征

use ArchTech\Enums\Values;

enum TaskStatus: int
{
    use Values;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use Values;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}

使用values()方法

TaskStatus::values(); // [0, 1, 2]
Role::values(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']

选项

此辅助工具返回支持枚举的案例名称和值的关联数组,或纯枚举的名称列表(使此函数与纯枚举的::names()功能等效)。

在您的枚举上应用特征

use ArchTech\Enums\Options;

enum TaskStatus: int
{
    use Options;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use Options;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}

使用options()方法

TaskStatus::options(); // ['INCOMPLETE' => 0, 'COMPLETED' => 1, 'CANCELED' => 2]
Role::options(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']

stringOptions()

特性还添加了stringOptions()方法,可用于生成枚举选项的便捷字符串表示形式

// First argument is the callback, second argument is glue
// returns "INCOMPLETE => 0, COMPLETED => 1, CANCELED => 2"
TaskStatus::stringOptions(fn ($name, $value) => "$name => $value", ', ');

对于纯枚举(非支持),使用名称代替$value(这意味着$name$value都是相同的)。

此方法的两个参数都是可选的,粘合剂默认为\n,回调默认为生成HTML <option> 标签

// <option value="0">Incomplete</option>
// <option value="1">Completed</option>
// <option value="2">Canceled</option>
TaskStatus::stringOptions(); // backed enum

// <option value="ADMINISTRATOR">Administrator</option>
// <option value="Subscriber">Subscriber</option>
// <option value="GUEST">Guest</option>
Role::stringOptions(); // pure enum

来自

此辅助工具向纯枚举添加from()tryFrom(),向所有枚举添加fromName()tryFromName()

重要提示

  • BackedEnum实例已经实现了自己的from()tryFrom()方法,这些方法不会被此特性覆盖。在BackedEnum中尝试覆盖这些方法会导致致命错误。
  • 纯枚举只有命名案例而没有值,因此from()tryFrom()方法在功能上等同于fromName()tryFromName()

在您的枚举上应用特征

use ArchTech\Enums\From;

enum TaskStatus: int
{
    use From;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use From;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}

使用from()方法

Role::from('ADMINISTRATOR'); // Role::ADMINISTRATOR
Role::from('NOBODY'); // Error: ValueError

使用tryFrom()方法

Role::tryFrom('GUEST'); // Role::GUEST
Role::tryFrom('NEVER'); // null

使用fromName()方法

TaskStatus::fromName('INCOMPLETE'); // TaskStatus::INCOMPLETE
TaskStatus::fromName('MISSING'); // Error: ValueError
Role::fromName('SUBSCRIBER'); // Role::SUBSCRIBER
Role::fromName('HACKER'); // Error: ValueError

使用tryFromName()方法

TaskStatus::tryFromName('COMPLETED'); // TaskStatus::COMPLETED
TaskStatus::tryFromName('NOTHING'); // null
Role::tryFromName('GUEST'); // Role::GUEST
Role::tryFromName('TESTER'); // null

元数据

此特性允许您为枚举案例添加元数据。

在您的枚举上应用特征

use ArchTech\Enums\Metadata;
use ArchTech\Enums\Meta\Meta;
use App\Enums\MetaProperties\{Description, Color};

#[Meta(Description::class, Color::class)]
enum TaskStatus: int
{
    use Metadata;

    #[Description('Incomplete Task')] #[Color('red')]
    case INCOMPLETE = 0;

    #[Description('Completed Task')] #[Color('green')]
    case COMPLETED = 1;

    #[Description('Canceled Task')] #[Color('gray')]
    case CANCELED = 2;
}

说明

  • DescriptionColor是用户空间类属性——元属性
  • #[Meta]调用启用了枚举上的这两个元属性
  • 每个案例都必须定义描述和颜色(在这个例子中)

访问元数据

TaskStatus::INCOMPLETE->description(); // 'Incomplete Task'
TaskStatus::COMPLETED->color(); // 'green'

创建元属性

每个元属性(=用于案例的属性)都需要作为一个类存在。

#[Attribute]
class Color extends MetaProperty {}

#[Attribute]
class Description extends MetaProperty {}

在类内部,您可以自定义一些功能。例如,您可能想要使用与类名派生的不同方法名(默认情况下,Description 变为 description())。为此,请在元属性上覆盖 method() 方法。

#[Attribute]
class Description extends MetaProperty
{
    public static function method(): string
    {
        return 'note';
    }
}

使用上述代码,案例的描述将可通过 TaskStatus::INCOMPLETE->note() 访问。

您还可以自定义传递的值。例如,要将颜色名称如 text-{$color}-500 包装起来,您需要添加以下 transform() 方法。

#[Attribute]
class Color extends MetaProperty
{
    protected function transform(mixed $value): mixed
    {
        return "text-{$value}-500";
    }
}

现在返回的颜色将被正确转换。

TaskStatus::COMPLETED->color(); // 'text-green-500'

您还可以添加一个 defaultValue() 方法,以指定如果案例未使用元属性,则应具有的值。这样,您可以在某些案例上应用属性,同时仍然可以在所有其他案例上获得可配置的默认值。

使用 fromMeta() 方法。

TaskStatus::fromMeta(Color::make('green')); // TaskStatus::COMPLETED
TaskStatus::fromMeta(Color::make('blue')); // Error: ValueError

使用 tryFromMeta() 方法。

TaskStatus::tryFromMeta(Color::make('green')); // TaskStatus::COMPLETED
TaskStatus::tryFromMeta(Color::make('blue')); // null

建议:使用注解和特性。

如果您想为元数据获取方法添加更好的IDE支持,可以使用 @method 注解。

/**
 * @method string description()
 * @method string color()
 */
#[Meta(Description::class, Color::class)]
enum TaskStatus: int
{
    use Metadata;

    #[Description('Incomplete Task')] #[Color('red')]
    case INCOMPLETE = 0;

    #[Description('Completed Task')] #[Color('green')]
    case COMPLETED = 1;

    #[Description('Canceled Task')] #[Color('gray')]
    case CANCELED = 2;
}

如果您在多个枚举中使用相同的元属性,您可以创建一个包含此 @method 注解的专用特性。

可比较的

此特性允许您使用 is()isNot()in()notIn() 比较枚举。

在您的枚举上应用特征

use ArchTech\Enums\Comparable;

enum TaskStatus: int
{
    use Comparable;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use Comparable;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}

使用 is() 方法。

TaskStatus::INCOMPLETE->is(TaskStatus::INCOMPLETE); // true
TaskStatus::INCOMPLETE->is(TaskStatus::COMPLETED); // false
Role::ADMINISTRATOR->is(Role::ADMINISTRATOR); // true
Role::ADMINISTRATOR->is(Role::NOBODY); // false

使用 isNot() 方法。

TaskStatus::INCOMPLETE->isNot(TaskStatus::INCOMPLETE); // false
TaskStatus::INCOMPLETE->isNot(TaskStatus::COMPLETED); // true
Role::ADMINISTRATOR->isNot(Role::ADMINISTRATOR); // false
Role::ADMINISTRATOR->isNot(Role::NOBODY); // true

使用 in() 方法。

TaskStatus::INCOMPLETE->in([TaskStatus::INCOMPLETE, TaskStatus::COMPLETED]); // true
TaskStatus::INCOMPLETE->in([TaskStatus::COMPLETED, TaskStatus::CANCELED]); // false
Role::ADMINISTRATOR->in([Role::ADMINISTRATOR, Role::GUEST]); // true
Role::ADMINISTRATOR->in([Role::SUBSCRIBER, Role::GUEST]); // false

使用 notIn() 方法。

TaskStatus::INCOMPLETE->notIn([TaskStatus::INCOMPLETE, TaskStatus::COMPLETED]); // false
TaskStatus::INCOMPLETE->notIn([TaskStatus::COMPLETED, TaskStatus::CANCELED]); // true
Role::ADMINISTRATOR->notIn([Role::ADMINISTRATOR, Role::GUEST]); // false
Role::ADMINISTRATOR->notIn([Role::SUBSCRIBER, Role::GUEST]); // true

PHPStan

要协助PHPStan使用可调用的案例,可以将PHPStan扩展包含到您的 phpstan.neon 文件中。

includes:
  - ./vendor/archtechx/enums/extension.neon

开发

在本地运行所有检查。

./check

代码样式将由 php-cs-fixer 自动修复。