framjet/enum-bitmask

一个小型库,为 PHP 8.1 枚举提供作为位掩码标志的功能

1.0.0 2021-12-28 17:48 UTC

This package is auto-updated.

Last update: 2024-08-29 00:05:22 UTC


README

Latest Stable Version Software License Build Status Total Downloads Dependents PHP Version Require Mutation testing badge Type Coverage

Email

一个小型库,为 PHP 8.1 枚举提供作为位掩码标志的功能。

为什么?

有时你需要在对象上添加一些标志来表示一些功能,通常使用类型为 bool 的简单属性,但随后你开始添加多个属性,然后你的对象大小(序列化/JSON)开始大幅增加。

位掩码值一直是标志的高效存储选项。它在一个 int32 值内提供多达 32 个独特的标志。

另一个大优点是可以在一个调用中执行 ANDORNOT 操作,而不是通过多个 if 表达式来检查所有这些属性值。

安装

通过 Composer

$ composer require framjet/enum-bitmask

用法

该库提供了一个特性 BitmaskFunctionality,它需要包含在整数支持的枚举中。

以下是一个使用 Enum 通过空间高效的位掩码整数值提供标志的简单示例

<?php

use FramJet\Packages\EnumBitmask\BitmaskFunctionality;

enum Flag: int
{
    use BitmaskFunctionality;

    case Public = 0b000001;
    case Protected = 0b000010;
    case Private = 0b000100;
    case ReadOnly = 0b001000;
    case Static = 0b010000;
    case Final = 0b100000;
}

class Member
{
    public function __construct(private int $flags = 0)
    {
    }

    public function setPublic(): void
    {
        $this->flags = Flag::set(
            Flag::clear($this->flags, Flag::Private, Flag::Protected),
            Flag::Public
        );
    }

    public function isPublic(): bool
    {
        return Flag::on($this->flags, Flag::Public);
    }

    public function isReadOnly(): bool
    {
        return Flag::on($this->flags, Flag::ReadOnly);
    }

    /** @return list<Flag> */
    public function getFlags(): array
    {
        return Flag::parse($this->flags);
    }

    public function getFlagsValue(): int
    {
        return $this->flags;
    }
}

class Container
{
    /** @param list<Member> $members */
    public function __construct(private array $members = [])
    {
    }

    public function addMember(Member $member): void
    {
        $this->members[] = $member;
    }

    public function getMembers(Flag ...$flags): array
    {
        return array_filter($this->members, static fn(Member $m) => Flag::any($m->getFlagsValue(), ...$flags));
    }
}

$memberPublic = new Member();
$memberPublic->setPublic();

$memberPublic->getFlags(); // [Flag::Public]

$memberReadOnly = new Member(Flag::build(Flag::ReadOnly));

$memberReadOnly->isReadOnly(); // true
$memberReadOnly->isPublic();   // false

$memberPrivate = new Member(Flag::build(Flag::Private, Flag::ReadOnly));

$memberPrivate->isReadOnly(); // true
$memberPrivate->isPublic();   // false
$memberPrivate->getFlags();   // [Flag::Private, Flag::ReadOnly]

array_map(
    static fn(Flag $f) => $f->toString(),
    $memberPrivate->getFlags()
); // ['0b0000_0000_0000_0000_0000_0000_0000_0100', '0b0000_0000_0000_0000_0000_0000_0000_1000']

$container = new Container();
$container->addMember($memberPublic);
$container->addMember($memberReadOnly);
$container->addMember($memberPrivate);

$container->getMembers();                             // [$memberPublic, $memberReadOnly, $memberPrivate]
$container->getMembers(Flag::Public);                 // [$memberPublic]
$container->getMembers(Flag::ReadOnly);               // [$memberReadOnly, $memberPrivate]
$container->getMembers(Flag::ReadOnly, Flag::Public); // [$memberPublic, $memberReadOnly, $memberPrivate]

许可证

有关更多信息,请参阅许可证文件