dnl-blkv / simple-php-enum
一个类似C/C++的简单枚举库。
Requires
- php: >=7.0
Requires (Dev)
- phpunit/phpunit: ^5.4
README
描述
一个简单的PHP枚举库,类似于C/C++。
统计数据和健康状态
PHP版本支持
该包是新的,因此只支持PHP >=7.0。
基本用法
安装
- 安装composer
- 在终端打开您的项目文件夹
- 输入
composer require dnl-blkv/simple-php-enum - 等待composer完成工作
- 现在,您可以按照以下说明开始使用Simple PHP Enums!
定义枚举
使用该包定义基本枚举非常简单
use dnl_blkv\enum\AbstractEnum;
/**
* @method static static CAT()
* @method static static DOG()
* @method static static BIRD()
* @method static static FISH()
*/
class AnimalEnum extends AbstractEnum
{
const CAT = null;
const DOG = null;
const BIRD = null;
const FISH = null;
}
在这里,null表示自动确定的序数值,或自动序数值。默认的自动序数值为0。后续的自动序数值按{上一个序数} + 1确定。
枚举常量名称必须符合PSR-1规范,并且必须以大写字母开头。如果常量名称不符合规则,则忽略该常量。
创建
一旦定义了类,就可以按以下方式获取枚举
$animal = AnimalEnum::CAT();
或者
$animal = AnimalEnum::getByName('CAT');
或者
$animal = AnimalEnum::getByOrdinal(0);
在上面的示例中,如果未定义名称或序数,将抛出异常(分别对应于UndefinedEnumNameException和UndefinedEnumOrdinalException)。
访问
您可以访问枚举的名称(字符串表示)和序数(数字表示)
echo $animal->getName() . ' ' . $animal->getOrdinal(); // Outputs "CAT 0"
比较
相等性
枚举可以这样检查相等性
$cat = AnimalEnum::CAT();
$otherCat = AnimalEnum::CAT();
$dog = AnimalEnum::DOG();
var_dump($cat->isEqual($otherCat)) // Outputs "bool(true)"
var_dump($cat->isEqual($dog)) // Outputs "bool(false)"
直观上,不同类型的两个枚举永远不会相等。如果我们有一个类型为SomeOtherEnum的枚举,其中const VALUE = 0;,则以下成立
var_dump(SomeOtherEnum::VALUE()->isEqual(AnimalEnum::CAT())) // Outputs "bool(false)"
按序数比较
还可以通过序数值比较Simple PHP Enums。为此定义了四个方法,如下所示
/**
* @method static static READ()
* @method static static WRITE()
* @method static static ADMIN()
*/
class AccessLevelEnum extends Enum
{
const READ = null;
const WRITE = null;
const ADMIN = null;
}
var_dump(AccessLevelEnum::READ()->isLess(AccessLevelEnum::WRITE())) . PHP_EOL // -> "bool(true)"
var_dump(AccessLevelEnum::READ()->isGreater(AccessLevelEnum::WRITE())) . PHP_EOL // -> "bool(false)"
var_dump(AccessLevelEnum::READ()->isGreaterOrEqual(AccessLevelEnum::READ())) . PHP_EOL // -> "bool(true)"
var_dump(AccessLevelEnum::READ()->isLessOrEqual(AccessLevelEnum::ADMIN())) . PHP_EOL // -> "bool(true)"
如果比较不同类型的两个枚举,则抛出InvalidArgumentException。
高级用法
使用自定义序数定义枚举
除了让库自动分配序数之外,您还可以手动将自定义整数值分配给序数
use dnl_blkv\enum\AbstractEnum;
/**
* @method static static PIZZA()
* @method static static SUSHI()
* @method static static KEBAB()
* @method static static SALAD()
*/
class FoodEnum extends AbstractEnum
{
const PIZZA = 5;
const SUSHI = null;
const KEBAB = 8;
const SALAD = 10;
}
在这种情况下,枚举将被定义为以下内容
echo FoodEnum::PIZZA()->getOrdinal() . PHP_EOL; // Outputs "5"
echo FoodEnum::SUSHI()->getOrdinal() . PHP_EOL; // Outputs "6"
echo FoodEnum::KEBAB()->getOrdinal() . PHP_EOL; // Outputs "8"
echo FoodEnum::SALAD()->getOrdinal() . PHP_EOL; // Outputs "10"
重复序数
类似于纯C/C++枚举,这个Simple PHP Enums允许重复序数。这可以用于处理默认值等类似情况
use dnl_blkv\enum\AbstractEnum;
/**
* @method static static LAGER()
* @method static static IPA()
* @method static static PORTER()
* @method static static STOUT()
* @method static static DEFAULT()
* @method static static AFTER_DEFAULT()
*/
class BeerEnum extends AbstractEnum
{
const LAGER = 0;
const IPA = null;
const PORTER = null;
const STOUT = null;
const DEFAULT = 0;
const AFTER_DEFAULT = null;
}
对于上面定义的枚举,以下将成立
echo BeerEnum::DEFAULT()->getOrdinal() . PHP_EOL; // Outputs "0"
echo BeerEnum::AFTER_DEFAULT()->getOrdinal() . PHP_EOL; // Outputs "1"
如果您通过魔术方法或名称获取具有重复序数的枚举,它将按常规工作。
echo BeerEnum::DEFAULT()->getName() . PHP_EOL; // Outputs "DEFAULT"
echo BeerEnum::getByName('DEFAULT')->getName() . PHP_EOL; // Outputs "DEFAULT"
然而,如果您通过序数获取它,行为略有不同,您有两种选择,如下所示
echo BeerEnum::getFirstByOrdinal(0)->getName() . PHP_EOL; // Outputs "LAGER"
$allEnumWithOrdinalZero = BeerEnum::getAllByOrdinal(0);
echo $allEnumWithOrdinalZero[0]->getName() . PHP_EOL; // Outputs "LAGER"
echo $allEnumWithOrdinalZero[1]->getName() . PHP_EOL; // Outputs "DEFAULT"
更多相等性
Simple PHP Enum库只创建每个枚举对象一次,然后重用它。因此,枚举可以通过===或其别名isSame进行比较。这种比较比isEqual更严格。而isEqual只考虑枚举类型和序数,isSame还考虑name。
var_dump(BeerEnum::LAGER()->isEqual(BeerEnum::LAGER())); // Outputs "bool(true)"
var_dump(BeerEnum::LAGER()->isEqual(BeerEnum::DEFAULT())); // Outputs "bool(true)"
var_dump(BeerEnum::LAGER() === BeerEnum::LAGER()); // Outputs "bool(true)"
var_dump(BeerEnum::LAGER() === BeerEnum::DEFAULT()); // Outputs "bool(false)"
var_dump(BeerEnum::LAGER()->isSame(BeerEnum::LAGER())); // Outputs "bool(true)"
var_dump(BeerEnum::LAGER()->isSame(BeerEnum::DEFAULT())); // Outputs "bool(false)"
检查名称和序数是否存在
如果您想检查某个枚举类型是否具有给定的名称或序数,有方法可以轻松完成此操作
var_dump(BeerEnum::isNameDefined('STOUT')) // Outputs "bool(true)";
var_dump(BeerEnum::isNameDefined('VODKA')) // Outputs "bool(false)";
var_dump(BeerEnum::isOrdinalDefined(3)) // Outputs "bool(true)";
var_dump(BeerEnum::isOrdinalDefined(420)) // Outputs "bool(false)";
转换为字符串
枚举具有内嵌的魔法机制进行序列化
echo BeerEnum::IPA() . PHP_EOL;
/*
* Outputs:
* {
* "\your\name\space\BeerEnum": {
* "name": "IPA",
* "ordinal": 1
* }
* }
*/
注意
扩展
AbstractEnum 类的所有内部成员都是 public 或 protected 的。因此,它完全开放以供扩展,允许你在此基础上构建更复杂的结构。
与数据库一起使用
如果你选择将枚举与数据库一起使用并存储序号,我建议确保没有存储的枚举具有重复的序号。否则,可能会出现存储 DEFAULT = 0,但在重新创建时接收到 IPA = 0 的情况。