Simple PHP Enum
Description
A simple C/C++ alike PHP library for Enums., (*1)
Stats and Health
, (*2)
PHP Version Support
The package is new and thus only supports PHP >=7.0
., (*3)
How To Basic
Installation
- Install composer
- Open your project folder in terminal
- Enter
composer require dnl-blkv/simple-php-enum
- Wait for the composer to finish the job
- Now, you can start using the Simple PHP Enums as described below!
Defining Enums
Defining a basic Enum with the package is straightforward:, (*4)
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;
}
Here null
means auto-determined ordinal value, or auto-ordinal. The default auto-ordinal is 0
. The further auto-ordinal values are determined as {previous ordinal} + 1
., (*5)
Enum constant names MUST be PSR-1-compliant AND start from a capital letter. If a constant name does not conform with the rules, the constant is ignored., (*6)
Creating
Once the class is defined, the enums can be acquired as:, (*7)
$animal = AnimalEnum::CAT();
Or:, (*8)
$animal = AnimalEnum::getByName('CAT');
Or:, (*9)
$animal = AnimalEnum::getByOrdinal(0);
In the examples above, if the name or the ordinal is not defined, exceptions will be thrown (UndefinedEnumNameException
and UndefinedEnumOrdinalException
correspondingly)., (*10)
Accessing
You can access the name (string representation) and the ordinal (numeric representation) of the enum:, (*11)
echo $animal->getName() . ' ' . $animal->getOrdinal(); // Outputs "CAT 0"
Comparison
Equality
The enums can be checked for equality as such:, (*12)
$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)"
Intuitively, two enums of different types are never equal. If we have an enum of type SomeOtherEnum
with const VALUE = 0;
then the following holds:, (*13)
var_dump(SomeOtherEnum::VALUE()->isEqual(AnimalEnum::CAT())) // Outputs "bool(false)"
Comparison by Ordinal
It is also possible to compare the Simple PHP Enums by their ordinal values. There are four methods defined for this, as shown below:, (*14)
/**
* @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)"
If two enums of different types are compared, the InvalidArgumentException
is thrown., (*15)
How To Advanced
Defining Enums with Custom Ordinals
Besides letting the library assign the ordinals automatically, you could manually assign custom integer values to the ordinals:, (*16)
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;
}
In this case the enums will be defined as following:, (*17)
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"
Duplicate Ordinals
Similarly to the vanilla C/C++ enums, this Simple PHP Enums allow for duplicate ordinals. This may be used for tackling such cases as a default value:, (*18)
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;
}
For the enum defined above, the following will hold:, (*19)
echo BeerEnum::DEFAULT()->getOrdinal() . PHP_EOL; // Outputs "0"
echo BeerEnum::AFTER_DEFAULT()->getOrdinal() . PHP_EOL; // Outputs "1"
If you are getting an enum with duplicate ordinal using a magic method or by name, it works as usual., (*20)
echo BeerEnum::DEFAULT()->getName() . PHP_EOL; // Outputs "DEFAULT"
echo BeerEnum::getByName('DEFAULT')->getName() . PHP_EOL; // Outputs "DEFAULT"
However, if you get it by an ordinal, the behavior is slightly different, and you have two options as shown below:, (*21)
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"
More Equality
The Simple PHP Enum library only creates each enum object once and then reuses it. Therefore, the enums are comparable with ===
or its alias isSame
. This kind comparison is stricter than isEqual
. Whereas isEqual
only accounts for the enum type and ordinal, isSame
also takes the name
into account:, (*22)
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)"
Checking Existence of Names and Ordinals
If you wish to check whether or not certain enum type has a given name or ordinal, there are methods allowing you to easily do so:, (*23)
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)";
Converting to String
The enums have an embedded magical mechanism for serialization:, (*24)
echo BeerEnum::IPA() . PHP_EOL;
/*
* Outputs:
* {
* "\your\name\space\BeerEnum": {
* "name": "IPA",
* "ordinal": 1
* }
* }
*/
Notes
Extension
All the internals of the AbstractEnum
class are either public
or protected
. Therefore, it is completely open for extension and allows you to build your own, more complex constructions on top of it., (*25)
Use with Databases
If you opt to use these enums with databases and store the ordinals, I would recommend to make sure that no stored enum has duplicate ordinals. Otherwise, it could happen that you store DEFAULT = 0
, but receive IPA = 0
upon recreation., (*26)