mediagone/types-enums

强类型枚举(类)用于模拟PHP 8.1的枚举。

0.1.5 2021-12-04 23:09 UTC

This package is auto-updated.

Last update: 2024-09-11 14:38:24 UTC


README

Latest Version on Packagist Total Downloads Software License

安装

此包需要 PHP 7.4+

将其作为Composer依赖项添加

$ composer require mediagone/types-enums

简介

使用常量表示可枚举值是不安全的,除非我们提供足够的检查来防止任何问题

class Article
{
    public const STATUS_DRAFT = 0;
    public const STATUS_PUBLISHED = 1;
    
    private int $status;
    
    public function changeStatus(int $status) : void
    {
        // We need need to check if the provided status value is valid.
        if (! in_array($status, [Article::STATUS_DRAFT, Article::STATUS_PUBLISHED], true)) {
            throw new LogicException("Invalid status ($status)");
        }
        
        $this->status = $status;
    }
}

$article->changeStatus(Article::STATUS_PUBLISHED); // valid
$article->changeStatus(1); // valid but not safe
$article->changeStatus(2); // invalid (and risky if there is no validity check in the method)


class OtherClass
{
    public const ANOTHER_INT_CONSTANT = 0;
}

$article->changeStatus(OtherClass::ANOTHER_INT_CONSTANT); // valid but senseless

使用强类型枚举代替PHP原始类型(int,string)可以在任何地方安全地类型提示它们,并确保您的数据有效,而无需在您的代码中添加任何检查。

遗憾的是,PHP在8.1之前没有提供原生的枚举,但可以使用类来模拟。

文档

简单用法

首先,创建一个枚举类,将您的可枚举值定义为私有常量
注意:将静态方法注释添加到您的类中,以在您的首选IDE中启用自动完成。

/**
 * @method static ArticleStatus DRAFT()
 * @method static ArticleStatus PUBLISHED()
 */
final class ArticleStatus extends EnumInt
{
    private const DRAFT = 0;
    private const PUBLISHED = 1;
}

现在,可以通过静态方法访问枚举值,这些方法返回一个ArticleStatus实例

ArticleStatus::DRAFT();
ArticleStatus::PUBLISHED();

// Strict comparisons are valid since methods always return the same instance
ArticleStatus::PUBLISHED() === ArticleStatus::PUBLISHED(); // true
ArticleStatus::DRAFT() === ArticleStatus::PUBLISHED(); // false

现在,您可以使用它作为常规的强类型属性

class Article
{
    private ArticleStatus $status;
    
    public function changeStatus(ArticleStatus $status) : void
    {
        // No check needed because $status is always a valid value.
        $this->status = $status;
    }
}

$article->changeStatus(ArticleStatus::PUBLISHED()); // valid
$article->changeStatus(1); // invalid

枚举信息

您可以通过使用->value->name属性来访问枚举的底层值和名称

final class ArticleStatus extends EnumInt
{
    private const DRAFT = 0;
    private const PUBLISHED = 1;
}

ArticleStatus::PUBLISHED()->value; // 1
ArticleStatus::PUBLISHED()->name; // "PUBLISHED"

序列化

由于PHP序列化机制不允许定义要恢复的实例,它完全破坏了库的工作方式和严格比较

$a = unserialize(serialize(ArticleStatus::PUBLISHED()));
$b = ArticleStatus::PUBLISHED();

$a === $b; // false

这就是为什么对所有枚举类禁用了serialize()unserialize()的原因。

如果您需要处理序列化,您必须手动存储枚举的值并在之后恢复它

$serializedValue = ArticleStatus::PUBLISHED()->value;

// restore the enum
$enum = ArticleStatus::from($serializedValue);

注意:不建议使用枚举名称进行序列化,因为代码重构可能会随时破坏它。

许可

Types Enums 在MIT许可下发布。请参阅LICENSE文件。