kuria/enum

PHP中的模拟枚举对象

v5.1.0 2019-01-28 12:36 UTC

This package is auto-updated.

Last update: 2024-09-22 17:34:17 UTC


README

PHP中的模拟枚举对象。

接口类似于 SplEnum,但不需要任何PHP扩展,并提供更多功能。

https://travis-ci.cn/kuria/enum.svg?branch=master

内容

特性

  • 不可变性
  • 确保键和值唯一
  • 简单易用(只需扩展一个类并定义一些类常量)
  • 许多与键相关的函数
  • 值及其枚举、映射和检查
  • 枚举实例
  • 详细的异常消息

要求

  • PHP 7.1+

用法

枚举

静态 Enum 类提供了对定义的键值对的访问。

定义枚举类

<?php

use Kuria\Enum\Enum;

abstract class DayOfTheWeek extends Enum
{
    const MONDAY = 0;
    const TUESDAY = 1;
    const WEDNESDAY = 2;
    const THURSDAY = 3;
    const FRIDAY = 4;
    const SATURDAY = 5;
    const SUNDAY = 6;
}

注意

私有和受保护的常量将被忽略。

自定义键值源

要使用除类常量以外的其他来源定义键值对,请重写静态 determineKeyToValueMap() 方法

<?php

use Kuria\Enum\Enum;

abstract class Example extends Enum
{
   protected static function determineKeyToValueMap(): array
   {
        return [
            'FOO' => 'bar',
            'BAZ' => 'qux',
            'QUUX' => 'quuz',
        ];
   }
}

支持的值类型

仅支持字符串、整数和null值。

当用作数组键时,值必须是唯一的。请参阅 值类型强制转换

值将根据与PHP数组键相同的类型强制转换规则进行查找和比较。请参阅 值类型强制转换

方法概述

检查键和值

验证键或值的存续性

<?php

var_dump(
    DayOfTheWeek::hasKey('MONDAY'),
    DayOfTheWeek::hasValue(0)
);

输出

bool(true)
bool(true)
确保键和值的存续性

确保键或值存在,否则抛出异常

<?php

DayOfTheWeek::ensureKey('MONDAY');
DayOfTheWeek::ensureValue(0);

请参阅 错误处理

获取值对应的键或键对应的值

可以使用它们的对应项查找键和值

<?php

var_dump(
    DayOfTheWeek::getValue('FRIDAY'),
    DayOfTheWeek::getKey(4)
);

输出

int(4)
string(6) "FRIDAY"

注意

如果键或值不存在,将抛出异常。请参阅 错误处理

要获取而不是异常的 NULL,请使用 findValue()findKey() 方法。

获取键/值列表和映射
<?php

echo 'DayOfTheWeek::getKeys(): '; print_r(DayOfTheWeek::getKeys());
echo 'DayOfTheWeek::getValues(): '; print_r(DayOfTheWeek::getValues());
echo 'DayOfTheWeek::getMap(): '; print_r(DayOfTheWeek::getMap());
echo 'DayOfTheWeek::getKeyMap(): '; print_r(DayOfTheWeek::getKeyMap());
echo 'DayOfTheWeek::getValueMap(): '; print_r(DayOfTheWeek::getValueMap());

输出

DayOfTheWeek::getKeys(): Array
(
    [0] => MONDAY
    [1] => TUESDAY
    [2] => WEDNESDAY
    [3] => THURSDAY
    [4] => FRIDAY
    [5] => SATURDAY
    [6] => SUNDAY
)
DayOfTheWeek::getValues(): Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
    [6] => 6
)
DayOfTheWeek::getMap(): Array
(
    [MONDAY] => 0
    [TUESDAY] => 1
    [WEDNESDAY] => 2
    [THURSDAY] => 3
    [FRIDAY] => 4
    [SATURDAY] => 5
    [SUNDAY] => 6
)
DayOfTheWeek::getKeyMap(): Array
(
    [MONDAY] => 1
    [TUESDAY] => 1
    [WEDNESDAY] => 1
    [THURSDAY] => 1
    [FRIDAY] => 1
    [SATURDAY] => 1
    [SUNDAY] => 1
)
DayOfTheWeek::getValueMap(): Array
(
    [0] => MONDAY
    [1] => TUESDAY
    [2] => WEDNESDAY
    [3] => THURSDAY
    [4] => FRIDAY
    [5] => SATURDAY
    [6] => SUNDAY
)
获取成对项

成对项是一个只有一个键及其相应值的数组。可以使用键或值检索它们

<?php

var_dump(DayOfTheWeek::getPair(DayOfTheWeek::MONDAY));
var_dump(DayOfTheWeek::getPairByKey('FRIDAY'));

输出

array(1) {
  ["MONDAY"]=>
  int(0)
}
array(1) {
  ["FRIDAY"]=>
  int(4)
}
计算成员数
<?php

var_dump(DayOfTheWeek::count());

输出

int(7)

EnumObject

EnumObject 类从 Enum 继承,并添加了创建实例的工厂方法。

定义枚举对象类

<?php

use Kuria\Enum\EnumObject;

/**
 * @method static static RED()
 * @method static static GREEN()
 * @method static static BLUE()
 */
class Color extends EnumObject
{
    const RED = 'r';
    const GREEN = 'g';
    const BLUE = 'b';
}

注意

@method 注解不是必需的,但它们将有助于代码补全和检查。

请参阅 魔法静态工厂方法

创建实例

可以通过一个工厂方法创建实例。这些实例在内部进行缓存和重用,因此对工厂方法的相同键或值的多个调用将产生相同的实例。

枚举实例不能被克隆。

使用值
<?php

$color = Color::fromValue(Color::RED);

var_dump($color);

输出

object(Foo\Color)#5 (2) {
  ["key"]=>
  string(3) "RED"
  ["value"]=>
  string(1) "r"
}
使用键
<?php

$color = Color::fromKey('GREEN');

var_dump($color);

输出

object(Foo\Color)#3 (2) {
  ["key"]=>
  string(5) "GREEN"
  ["value"]=>
  string(1) "g"
}
使用魔法静态工厂方法

对于每个键,都有一个同名的静态方法,它返回该键值对的实例。

<?php

$color = Color::BLUE();

var_dump($color);

输出

object(Foo\Color)#5 (2) {
  ["key"]=>
  string(4) "BLUE"
  ["value"]=>
  string(1) "b"
}

警告

魔法静态工厂方法名称区分大小写。

获取所有实例
<?php

var_dump(Color::all());

输出

array(3) {
  ["RED"]=>
  object(Foo\Color)#5 (2) {
    ["key"]=>
    string(3) "RED"
    ["value"]=>
    string(1) "r"
  }
  ["GREEN"]=>
  object(Foo\Color)#4 (2) {
    ["key"]=>
    string(5) "GREEN"
    ["value"]=>
    string(1) "g"
  }
  ["BLUE"]=>
  object(Foo\Color)#2 (2) {
    ["key"]=>
    string(4) "BLUE"
    ["value"]=>
    string(1) "b"
  }
}

方法概述

获取键和值
<?php

$color = Color::RED();

var_dump(
    $color->key(),
    $color->value()
);

输出

string(3) "RED"
string(1) "r"
获取成对项
<?php

$color = Color::GREEN();

var_dump($color->pair());

输出

array(1) {
  ["GREEN"]=>
  string(1) "g"
}
比较键和值
<?php

 $color = Color::RED();

 var_dump(
     $color->is('RED'),   // compare key
     $color->is('GREEN'), // compare key
     $color->equals('r'), // compare value
     $color->equals('g')  // compare value
 );

输出

bool(true)
bool(false)
bool(true)
bool(false)
字符串转换

将实例转换为字符串将返回其值(转换为字符串)

<?php

$color = Color::BLUE();

echo $color;

输出

b

错误处理

大多数错误状态通过抛出异常来处理。

所有由枚举类抛出的异常都实现了Kuria\Enum\Exception\ExceptionInterface

  • 当键不存在时抛出Kuria\Enum\Exception\InvalidKeyException
  • 当值不存在时抛出Kuria\Enum\Exception\InvalidValueException
  • 当魔法工厂方法不存在时抛出Kuria\Enum\Exception\InvalidMethodException
  • 当枚举类定义了重复的值时抛出Kuria\Enum\Exception\DuplicateValueException

值类型强制转换

查找值并与PHP数组键相同的类型强制规则进行比较。有关详细说明,请参阅PHP手册

支持字符串、整数和null作为值类型,这意味着以下值相等

  • null""(一个空字符串)
  • 123"123"(一个数字字符串)

注意

公共API,例如Enum::getValue()EnumObject::value(),始终返回枚举类中定义的值。

注意

数组键类型强制与宽松比较(==)不同。

示例

<?php

use Kuria\Enum\EnumObject;

class IntAndNullEnum extends EnumObject
{
    const INT_KEY = 123;
    const NULL_KEY = null;
}

class StringEnum extends EnumObject
{
    const NUMERIC_STRING_KEY = '123';
    const EMPTY_STRING_KEY = '';
}

// value checks
var_dump(
    IntAndNullEnum::hasValue('123'),
    IntAndNullEnum::hasValue('0123'),
    IntAndNullEnum::hasValue(''),
    IntAndNullEnum::hasValue(' '),
    StringEnum::hasValue(123),
    StringEnum::hasValue('0123'),
    StringEnum::hasValue(null),
    StringEnum::hasValue(' ')
);

// value retrieval
var_dump(
    (IntAndNullEnum::fromValue('123'))->value(),
    (IntAndNullEnum::fromValue(''))->value(),
    (StringEnum::fromValue(123))->value(),
    (StringEnum::fromValue(null))->value()
);

值检查输出

bool(true)    // '123' matches 123
bool(false)   // '0123' does not match 123
bool(true)    // '' matches NULL
bool(false)   // ' ' does not match NULL
bool(true)    // 123 matches '123'
bool(false)   // '0123' does not match '123'
bool(true)    // NULL matches ''
bool(false)   // ' ' does not match ''

值检索输出

int(123)          // enum created with '123' but 123 is returned
NULL              // enum created with '' but NULL is returned
string(3) "123"   // enum created with 123 but '123' is returned
string(0) ""      // enum created with NULL but '' is returned