<?php
class YourClass{const SOME_CONSTANT = 1;
public function echoConstant(){echo self::SOME_CONSTANT;}}
echo YourClass::SOME_CONSTANT;
$c = new YourClass;$c->echoConstant();
<?php
/*** Class Enum** @author Christopher Fox <christopher.fox@gmx.de>** @version 1.0** This class provides the function of an enumeration.* The values of Enum elements are unique (even between different Enums)* as you would expect them to be.** Constructing a new Enum:* ========================** In the following example we construct an enum called "UserState"* with the elements "inactive", "active", "banned" and "deleted".** <code>* Enum::Create('UserState', 'inactive', 'active', 'banned', 'deleted');* </code>** Using Enums:* ============** The following example demonstrates how to compare two Enum elements** <code>* var_dump(UserState::inactive == UserState::banned); // result: false* var_dump(UserState::active == UserState::active); // result: true* </code>** Special Enum methods:* =====================** Get the number of elements in an Enum:** <code>* echo UserState::CountEntries(); // result: 4* </code>** Get a list with all elements of the Enum:** <code>* $allUserStates = UserState::GetEntries();* </code>** Get a name of an element:** <code>* echo UserState::GetName(UserState::deleted); // result: deleted* </code>** Get an integer ID for an element (e.g. to store as a value in a database table):* This is simply the index of the element (beginning with 1).* Note that this ID is only unique for this Enum but now between different Enums.** <code>* echo UserState::GetDatabaseID(UserState::active); // result: 2* </code>*/class Enum{
/*** @var Enum $instance The only instance of Enum (Singleton)*/private static $instance;
/*** @var array $enums An array of all enums with Enum names as keys* and arrays of element names as values*/private $enums;
/*** Constructs (the only) Enum instance*/private function __construct(){$this->enums = array();}
/*** Constructs a new enum** @param string $name The class name for the enum* @param mixed $_ A list of strings to use as names for enum entries*/public static function Create($name, $_){// Create (the only) Enum instance if this hasn't happened yetif (self::$instance===null){self::$instance = new Enum();}
// Fetch the arguments of the function$args = func_get_args();// Exclude the "name" argument from the array of function arguments,// so only the enum element names remain in the arrayarray_shift($args);self::$instance->add($name, $args);}
/*** Creates an enumeration if this hasn't happened yet** @param string $name The class name for the enum* @param array $fields The names of the enum elements*/private function add($name, $fields){if (!array_key_exists($name, $this->enums)){$this->enums[$name] = array();
// Generate the code of the class for this enumeration$classDeclaration = "class " . $name . " {\n". "private static \$name = '" . $name . "';\n". $this->getClassConstants($name, $fields). $this->getFunctionGetEntries($name). $this->getFunctionCountEntries($name). $this->getFunctionGetDatabaseID(). $this->getFunctionGetName(). "}";
// Create the class for this enumerationeval($classDeclaration);}}
/*** Returns the code of the class constants* for an enumeration. These are the representations* of the elements.** @param string $name The class name for the enum* @param array $fields The names of the enum elements** @return string The code of the class constants*/private function getClassConstants($name, $fields){$constants = '';
foreach ($fields as $field){// Create a unique ID for the Enum element// This ID is unique because class and variables// names can't contain a semicolon. Therefore we// can use the semicolon as a separator here.$uniqueID = $name . ";" . $field;$constants .= "const " . $field . " = '". $uniqueID . "';\n";// Store the unique IDarray_push($this->enums[$name], $uniqueID);}
return $constants;}
/*** Returns the code of the function "GetEntries()"* for an enumeration** @param string $name The class name for the enum** @return string The code of the function "GetEntries()"*/private function getFunctionGetEntries($name){$entryList = '';
// Put the unique element IDs in single quotes and// separate them with commasforeach ($this->enums[$name] as $key => $entry){if ($key > 0) $entryList .= ',';$entryList .= "'" . $entry . "'";}
return "public static function GetEntries() { \n". " return array(" . $entryList . ");\n". "}\n";}
/*** Returns the code of the function "CountEntries()"* for an enumeration** @param string $name The class name for the enum** @return string The code of the function "CountEntries()"*/private function getFunctionCountEntries($name){// This function will simply return a constant number (e.g. return 5;)return "public static function CountEntries() { \n". " return " . count($this->enums[$name]) . ";\n". "}\n";}
/*** Returns the code of the function "GetDatabaseID()"* for an enumeration** @return string The code of the function "GetDatabaseID()"*/private function getFunctionGetDatabaseID(){// Check for the index of this element inside of the array// of elements and add +1return "public static function GetDatabaseID(\$entry) { \n". "\$key = array_search(\$entry, self::GetEntries());\n". " return \$key + 1;\n". "}\n";}
/*** Returns the code of the function "GetName()"* for an enumeration** @return string The code of the function "GetName()"*/private function getFunctionGetName(){// Remove the class name from the unique ID// and return this value (which is the element name)return "public static function GetName(\$entry) { \n". "return substr(\$entry, strlen(self::\$name) + 1 , strlen(\$entry));\n". "}\n";}
}
?>
class SomeTypeName {private static $enum = array(1 => "Read", 2 => "Write");
public function toOrdinal($name) {return array_search($name, self::$enum);}
public function toString($ordinal) {return self::$enum[$ordinal];}}
final class EnumException extends Exception{}
abstract class Enum{/*** @var array ReflectionClass*/protected static $reflectorInstances = array();/*** Массив конфигурированного объекта-константы enum* @var array*/protected static $enumInstances = array();/*** Массив соответствий значение->ключ используется для проверки -* если ли константа с таким значением* @var array*/protected static $foundNameValueLink = array();
protected $constName;protected $constValue;
/*** Реализует паттерн "Одиночка"* Возвращает объект константы, но но как объект его использовать не стоит,* т.к. для него реализован "волшебный метод" __toString()* Это должно использоваться только для типизачии его как параметра* @paradm Node*/final public static function get($value){// Это остается здесь для увеличения производительности (по замерам ~10%)$name = self::getName($value);if ($name === false)throw new EnumException("Неизвестая константа");$className = get_called_class();if (!isset(self::$enumInstances[$className][$name])){$value = constant($className.'::'.$name);self::$enumInstances[$className][$name] = new $className($name, $value);}
return self::$enumInstances[$className][$name];}
/*** Возвращает массив констант пар ключ-значение всего перечисления* @return array*/final public static function toArray(){$classConstantsArray = self::getReflectorInstance()->getConstants();foreach ($classConstantsArray as $k => $v)$classConstantsArray[$k] = (string)$v;return $classConstantsArray;}
/*** Для последующего использования в toArray для получения массива констант ключ->значение* @return ReflectionClass*/final private static function getReflectorInstance(){$className = get_called_class();if (!isset(self::$reflectorInstances[$className])){self::$reflectorInstances[$className] = new ReflectionClass($className);}return self::$reflectorInstances[$className];}
/*** Получает имя константы по её значению* @param string $value*/final public static function getName($value){$className = (string)get_called_class();
$value = (string)$value;if (!isset(self::$foundNameValueLink[$className][$value])){$constantName = array_search($value, self::toArray(), true);self::$foundNameValueLink[$className][$value] = $constantName;}return self::$foundNameValueLink[$className][$value];}
/*** Используется ли такое имя константы в перечислении* @param string $name*/final public static function isExistName($name){$constArray = self::toArray();return isset($constArray[$name]);}
/*** Используется ли такое значение константы в перечислении* @param string $value*/final public static function isExistValue($value){return self::getName($value) === false ? false : true;}
final private function __clone(){}
final private function __construct($name, $value){$this->constName = $name;$this->constValue = $value;}
final public function __toString(){return (string)$this->constValue;}}
用法:
class enumWorkType extends Enum{const FULL = 0;const SHORT = 1;}
class FruitsEnum {
static $APPLE = null;static $ORANGE = null;
private $value = null;
public static $map;
public function __construct($value) {$this->value = $value;}
public static function init () {self::$APPLE = new FruitsEnum("Apple");self::$ORANGE = new FruitsEnum("Orange");//static map to get object by name - example Enum::get("INIT") - returns Enum::$INIT object;self::$map = array ("Apple" => self::$APPLE,"Orange" => self::$ORANGE);}
public static function get($element) {if($element == null)return null;return self::$map[$element];}
public function getValue() {return $this->value;}
public function equals(FruitsEnum $element) {return $element->getValue() == $this->getValue();}
public function __toString () {return $this->value;}}FruitsEnum::init();
var_dump(FruitsEnum::$APPLE->equals(FruitsEnum::$APPLE)); //truevar_dump(FruitsEnum::$APPLE->equals(FruitsEnum::$ORANGE)); //falsevar_dump(FruitsEnum::$APPLE instanceof FruitsEnum); //truevar_dump(FruitsEnum::get("Apple")->equals(FruitsEnum::$APPLE)); //true - enum from stringvar_dump(FruitsEnum::get("Apple")->equals(FruitsEnum::get("Orange"))); //false
/*** A base class for enums.** This class can be used as a base class for enums.* It can be used to create regular enums (incremental indices), but it can also be used to create binary flag values.* To create an enum class you can simply extend this class, and make a call to <yourEnumClass>::init() before you use the enum.* Preferably this call is made directly after the class declaration.* Example usages:* DaysOfTheWeek.class.php* abstract class DaysOfTheWeek extends Enum{* static $MONDAY = 1;* static $TUESDAY;* static $WEDNESDAY;* static $THURSDAY;* static $FRIDAY;* static $SATURDAY;* static $SUNDAY;* }* DaysOfTheWeek::init();** example.php* require_once("DaysOfTheWeek.class.php");* $today = date('N');* if ($today == DaysOfTheWeek::$SUNDAY || $today == DaysOfTheWeek::$SATURDAY)* echo "It's weekend!";** Flags.class.php* abstract class Flags extends Enum{* static $FLAG_1;* static $FLAG_2;* static $FLAG_3;* }* Flags::init(Enum::$BINARY_FLAG);** example2.php* require_once("Flags.class.php");* $flags = Flags::$FLAG_1 | Flags::$FLAG_2;* if ($flags & Flags::$FLAG_1)* echo "Flag_1 is set";** @author Tiddo Langerak*/abstract class Enum{
static $BINARY_FLAG = 1;/*** This function must be called to initialize the enumeration!** @param bool $flags If the USE_BINARY flag is provided, the enum values will be binary flag values. Default: no flags set.*/public static function init($flags = 0){//First, we want to get a list of all static properties of the enum class. We'll use the ReflectionClass for this.$enum = get_called_class();$ref = new ReflectionClass($enum);$items = $ref->getStaticProperties();//Now we can start assigning values to the items.if ($flags & self::$BINARY_FLAG){//If we want binary flag values, our first value should be 1.$value = 1;//Now we can set the values for all items.foreach ($items as $key=>$item){if (!isset($item)){//If no value is set manually, we should set it.$enum::$$key = $value;//And we need to calculate the new value$value *= 2;} else {//If there was already a value set, we will continue starting from that value, but only if that was a valid binary flag value.//Otherwise, we will just skip this item.if ($key != 0 && ($key & ($key - 1) == 0))$value = 2 * $item;}}} else {//If we want to use regular indices, we'll start with index 0.$value = 0;//Now we can set the values for all items.foreach ($items as $key=>$item){if (!isset($item)){//If no value is set manually, we should set it, and increment the value for the next item.$enum::$$key = $value;$value++;} else {//If a value was already set, we'll continue from that value.$value = $item+1;}}}}}
class DaysOfWeek{const Sunday = 0;const Monday = 1;// etc.
private $intVal;private function __construct($intVal){$this->intVal = $intVal;}
//static instantiation methodspublic static function MONDAY(){return new self(self::Monday);}//etc.}
//function using type checkingfunction printDayOfWeek(DaysOfWeek $d){ //compiler can now use type checking// to something with $d...}
//calling the function is safe!printDayOfWeek(DaysOfWeek::MONDAY());
printDayOfWeek(DaysOfWeek::Monday); //triggers a compiler error.
这是错误的(调用整数常量)。我们可以使用私有静态变量而不是常量来防止这种情况:
class DaysOfWeeks{
private static $monday = 1;//etc.
private $intVal;//private constructorprivate function __construct($intVal){$this->intVal = $intVal;}
//public instantiation methodspublic static function MONDAY(){return new self(self::$monday);}//etc.
//convert an instance to its integer valuepublic function intVal(){return $this->intVal;}
}
<?php
abstract class AbstractEnum{/** @var array cache of all enum instances by class name and integer value */private static $allEnumMembers = array();
/** @var mixed */private $code;
/** @var string */private $description;
/*** Return an enum instance of the concrete type on which this static method is called, assuming an instance* exists for the passed in value. Otherwise an exception is thrown.** @param $code* @return AbstractEnum* @throws Exception*/public static function getByCode($code){$concreteMembers = &self::getConcreteMembers();
if (array_key_exists($code, $concreteMembers)) {return $concreteMembers[$code];}
throw new Exception("Value '$code' does not exist for enum '".get_called_class()."'");}
public static function getAllMembers(){return self::getConcreteMembers();}
/*** Create, cache and return an instance of the concrete enum type for the supplied primitive value.** @param mixed $code code to uniquely identify this enum* @param string $description* @throws Exception* @return AbstractEnum*/protected static function enum($code, $description){$concreteMembers = &self::getConcreteMembers();
if (array_key_exists($code, $concreteMembers)) {throw new Exception("Value '$code' has already been added to enum '".get_called_class()."'");}
$concreteMembers[$code] = $concreteEnumInstance = new static($code, $description);
return $concreteEnumInstance;}
/*** @return AbstractEnum[]*/private static function &getConcreteMembers() {$thisClassName = get_called_class();
if (!array_key_exists($thisClassName, self::$allEnumMembers)) {$concreteMembers = array();self::$allEnumMembers[$thisClassName] = $concreteMembers;}
return self::$allEnumMembers[$thisClassName];}
private function __construct($code, $description){$this->code = $code;$this->description = $description;}
public function getCode(){return $this->code;}
public function getDescription(){return $this->description;}}
下面是一个具体枚举的例子:
<?php
require('AbstractEnum.php');
class EMyEnum extends AbstractEnum{/** @var EMyEnum */public static $MY_FIRST_VALUE;/** @var EMyEnum */public static $MY_SECOND_VALUE;/** @var EMyEnum */public static $MY_THIRD_VALUE;
public static function _init(){self::$MY_FIRST_VALUE = self::enum(1, 'My first value');self::$MY_SECOND_VALUE = self::enum(2, 'My second value');self::$MY_THIRD_VALUE = self::enum(3, 'My third value');}}
EMyEnum::_init();
array(3) {[1]=>object(EMyEnum)#1 (2) {["code":"AbstractEnum":private]=>int(1)["description":"AbstractEnum":private]=>string(14) "My first value"}[2]=>object(EMyEnum)#2 (2) {["code":"AbstractEnum":private]=>int(2)["description":"AbstractEnum":private]=>string(15) "My second value"}[3]=>object(EMyEnum)#3 (2) {["code":"AbstractEnum":private]=>int(3)["description":"AbstractEnum":private]=>string(14) "My third value"}}
abstract class Enumeration{public static function enum(){$reflect = new ReflectionClass( get_called_class() );return $reflect->getConstants();}}
class Test extends Enumeration{const A = 'a';const B = 'b';}
foreach (Test::enum() as $key => $value) {echo "$key -> $value<br>";}
abstract class Enum{
const NONE = null;
final private function __construct(){throw new NotSupportedException(); //}
final private function __clone(){throw new NotSupportedException();}
final public static function toArray(){return (new ReflectionClass(static::class))->getConstants();}
final public static function isValid($value){return in_array($value, static::toArray());}
}
示例枚举:
final class ResponseStatusCode extends Enum{
const OK = 200;const CREATED = 201;const ACCEPTED = 202;// ...const SERVICE_UNAVAILABLE = 503;const GATEWAY_TIME_OUT = 504;const HTTP_VERSION_NOT_SUPPORTED = 505;
}
abstract class TypedEnum{private static $_instancedValues;
private $_value;private $_name;
private function __construct($value, $name){$this->_value = $value;$this->_name = $name;}
private static function _fromGetter($getter, $value){$reflectionClass = new ReflectionClass(get_called_class());$methods = $reflectionClass->getMethods(ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC);$className = get_called_class();
foreach($methods as $method){if ($method->class === $className){$enumItem = $method->invoke(null);
if ($enumItem instanceof $className && $enumItem->$getter() === $value){return $enumItem;}}}
throw new OutOfRangeException();}
protected static function _create($value){if (self::$_instancedValues === null){self::$_instancedValues = array();}
$className = get_called_class();
if (!isset(self::$_instancedValues[$className])){self::$_instancedValues[$className] = array();}
if (!isset(self::$_instancedValues[$className][$value])){$debugTrace = debug_backtrace();$lastCaller = array_shift($debugTrace);
while ($lastCaller['class'] !== $className && count($debugTrace) > 0){$lastCaller = array_shift($debugTrace);}
self::$_instancedValues[$className][$value] = new static($value, $lastCaller['function']);}
return self::$_instancedValues[$className][$value];}
public static function fromValue($value){return self::_fromGetter('getValue', $value);}
public static function fromName($value){return self::_fromGetter('getName', $value);}
public function getValue(){return $this->_value;}
public function getName(){return $this->_name;}}
示例枚举:
final class DaysOfWeek extends TypedEnum{public static function Sunday() { return self::_create(0); }public static function Monday() { return self::_create(1); }public static function Tuesday() { return self::_create(2); }public static function Wednesday() { return self::_create(3); }public static function Thursday() { return self::_create(4); }public static function Friday() { return self::_create(5); }public static function Saturday() { return self::_create(6); }}
示例用法:
function saveEvent(DaysOfWeek $weekDay, $comment){// store week day numeric value and comment:$myDatabase->save('myeventtable',array('weekday_id' => $weekDay->getValue()),array('comment' => $comment));}
// call the function, note: DaysOfWeek::Monday() returns an object of type DaysOfWeeksaveEvent(DaysOfWeek::Monday(), 'some comment');
class Fruit extends Enum {static public $APPLE = 1;static public $ORANGE = 2;}Fruit::initialize(); //Can also be called in autoloader
切换到枚举
$myFruit = Fruit::$APPLE;
switch ($myFruit) {case Fruit::$APPLE : echo "I like apples\n"; break;case Fruit::$ORANGE : echo "I hate oranges\n"; break;}
>> I like apples
将Enum作为参数传递(强类型)
/** Function only accepts Fruit enums as input**/function echoFruit(Fruit $fruit) {echo $fruit->getName().": ".$fruit->getValue()."\n";}
/** Call function with each Enum value that Fruit has */foreach (Fruit::getList() as $fruit) {echoFruit($fruit);}
//Call function with Apple enumechoFruit(Fruit::$APPLE)
//Will produce an error. This solution is strongly typedechoFruit(2);
>> APPLE: 1>> ORANGE: 2>> APPLE: 1>> Argument 1 passed to echoFruit() must be an instance of Fruit, integer given
Echo枚举为字符串
echo "I have an $myFruit\n";
>> I have an APPLE
按整数获取枚举
$myFruit = Fruit::getByValue(2);
echo "Now I have an $myFruit\n";
>> Now I have an ORANGE
按名称获取枚举
$myFruit = Fruit::getByName("APPLE");
echo "But I definitely prefer an $myFruit\n\n";
>> But I definitely prefer an APPLE
枚举类:
/*** @author Torge Kummerow*/class Enum {
/*** Holds the values for each type of Enum*/static private $list = array();
/*** Initializes the enum values by replacing the number with an instance of itself* using reflection*/static public function initialize() {$className = get_called_class();$class = new ReflectionClass($className);$staticProperties = $class->getStaticProperties();
self::$list[$className] = array();
foreach ($staticProperties as $propertyName => &$value) {if ($propertyName == 'list')continue;
$enum = new $className($propertyName, $value);$class->setStaticPropertyValue($propertyName, $enum);self::$list[$className][$propertyName] = $enum;} unset($value);}
/*** Gets the enum for the given value** @param integer $value* @throws Exception** @return Enum*/static public function getByValue($value) {$className = get_called_class();foreach (self::$list[$className] as $propertyName=>&$enum) {/* @var $enum Enum */if ($enum->value == $value)return $enum;} unset($enum);
throw new Exception("No such enum with value=$value of type ".get_called_class());}
/*** Gets the enum for the given name** @param string $name* @throws Exception** @return Enum*/static public function getByName($name) {$className = get_called_class();if (array_key_exists($name, static::$list[$className]))return self::$list[$className][$name];
throw new Exception("No such enum ".get_called_class()."::\$$name");}
/*** Returns the list of all enum variants* @return Array of Enum*/static public function getList() {$className = get_called_class();return self::$list[$className];}
private $name;private $value;
public function __construct($name, $value) {$this->name = $name;$this->value = $value;}
public function __toString() {return $this->name;}
public function getValue() {return $this->value;}
public function getName() {return $this->name;}
}
添加
当然你也可以为IDE添加注释
class Fruit extends Enum {
/*** This comment is for autocomplete support in common IDEs* @var Fruit A yummy apple*/static public $APPLE = 1;
/*** This comment is for autocomplete support in common IDEs* @var Fruit A sour orange*/static public $ORANGE = 2;}
//This can also go to the autoloader if available.Fruit::initialize();
class DayOfWeek {static $values = array(self::MONDAY,self::TUESDAY,// ...);
const MONDAY = 0;const TUESDAY = 1;// ...}
$today = DayOfWeek::MONDAY;
// If you want to check if a value is validassert( in_array( $today, DayOfWeek::$values ) );
class ShirtSize {private $size;private function __construct ($size) {$this->size = $size;}public function equals (ShirtSize $s) {return $this->size === $s->size;}public static function SMALL () { return new self(1); }public static function MEDIUM () { return new self(2); }public static function LARGE () { return new self(3); }}
然后我们可以像这样使用ShirtSize:
function sizeIsAvailable ($productId, ShirtSize $size) {// business magic}if(sizeIsAvailable($_GET["id"], ShirtSize::LARGE())) {echo "Available";} else {echo "Out of stock.";}$s2 = ShirtSize::SMALL();$s3 = ShirtSize::MEDIUM();echo $s2->equals($s3) ? "SMALL == MEDIUM" : "SMALL != MEDIUM";
<?php################################################################################# Class ENUMS## Original code by Mark Manning.# Copyrighted (c) 2015 by Mark Manning.# All rights reserved.## This set of code is hereby placed into the free software universe# via the GNU greater license thus placing it under the Copyleft# rules and regulations with the following modifications:## 1. You may use this work in any other work. Commercial or otherwise.# 2. You may make as much money as you can with it.# 3. You owe me nothing except to give me a small blurb somewhere in# your program or maybe have pity on me and donate a dollar to# sim_sales@paypal.com. :-)## Blurb:## PHP Class Enums by Mark Manning (markem-AT-sim1-DOT-us).# Used with permission.## Notes:## VIM formatting. Set tabs to four(4) spaces.#################################################################################class enums{private $enums;private $clear_flag;private $last_value;
################################################################################# __construct(). Construction function. Optionally pass in your enums.################################################################################function __construct(){$this->enums = array();$this->clear_flag = false;$this->last_value = 0;
if( func_num_args() > 0 ){return $this->put( func_get_args() );}
return true;}################################################################################# put(). Insert one or more enums.################################################################################function put(){$args = func_get_args();## Did they send us an array of enums?# Ex: $c->put( array( "a"=>0, "b"=>1,...) );# OR $c->put( array( "a", "b", "c",... ) );#if( is_array($args[0]) ){## Add them all in#foreach( $args[0] as $k=>$v ){## Don't let them change it once it is set.# Remove the IF statement if you want to be able to modify the enums.#if( !isset($this->enums[$k]) ){## If they sent an array of enums like this: "a","b","c",... then we have to# change that to be "A"=>#. Where "#" is the current count of the enums.#if( is_numeric($k) ){$this->enums[$v] = $this->last_value++;}## Else - they sent "a"=>"A", "b"=>"B", "c"=>"C"...#else {$this->last_value = $v + 1;$this->enums[$k] = $v;}}}}## Nope! Did they just sent us one enum?#else {## Is this just a default declaration?# Ex: $c->put( "a" );#if( count($args) < 2 ){## Again - remove the IF statement if you want to be able to change the enums.#if( !isset($this->enums[$args[0]]) ){$this->enums[$args[0]] = $this->last_value++;}## No - they sent us a regular enum# Ex: $c->put( "a", "This is the first enum" );#else {## Again - remove the IF statement if you want to be able to change the enums.#if( !isset($this->enums[$args[0]]) ){$this->last_value = $args[1] + 1;$this->enums[$args[0]] = $args[1];}}}}
return true;}################################################################################# get(). Get one or more enums.################################################################################function get(){$num = func_num_args();$args = func_get_args();## Is this an array of enums request? (ie: $c->get(array("a","b","c"...)) )#if( is_array($args[0]) ){$ary = array();foreach( $args[0] as $k=>$v ){$ary[$v] = $this->enums[$v];}
return $ary;}## Is it just ONE enum they want? (ie: $c->get("a") )#else if( ($num > 0) && ($num < 2) ){return $this->enums[$args[0]];}## Is it a list of enums they want? (ie: $c->get( "a", "b", "c"...) )#else if( $num > 1 ){$ary = array();foreach( $args as $k=>$v ){$ary[$v] = $this->enums[$v];}
return $ary;}## They either sent something funky or nothing at all.#return false;}################################################################################# clear(). Clear out the enum array.# Optional. Set the flag in the __construct function.# After all, ENUMS are supposed to be constant.################################################################################function clear(){if( $clear_flag ){unset( $this->enums );$this->enums = array();}
return true;}################################################################################# __call(). In case someone tries to blow up the class.################################################################################function __call( $name, $arguments ){if( isset($this->enums[$name]) ){ return $this->enums[$name]; }else if( !isset($this->enums[$name]) && (count($arguments) > 0) ){$this->last_value = $arguments[0] + 1;$this->enums[$name] = $arguments[0];return true;}else if( !isset($this->enums[$name]) && (count($arguments) < 1) ){$this->enums[$name] = $this->last_value++;return true;}
return false;}################################################################################# __get(). Gets the value.################################################################################function __get($name){if( isset($this->enums[$name]) ){ return $this->enums[$name]; }else if( !isset($this->enums[$name]) ){$this->enums[$name] = $this->last_value++;return true;}
return false;}################################################################################# __set(). Sets the value.################################################################################function __set( $name, $value=null ){if( isset($this->enums[$name]) ){ return false; }else if( !isset($this->enums[$name]) && !is_null($value) ){$this->last_value = $value + 1;$this->enums[$name] = $value;return true;}else if( !isset($this->enums[$name]) && is_null($value) ){$this->enums[$name] = $this->last_value++;return true;}
return false;}################################################################################# __destruct(). Deconstruct the class. Remove the list of enums.################################################################################function __destruct(){unset( $this->enums );$this->enums = null;
return true;}
}## Test code## $c = new enums();# $c->RED_LIGHT(85);# $c->YELLOW_LIGHT = 23;# $c->GREEN_LIGHT;## echo $c->RED_LIGHT . "\n";# echo $c->YELLOW_LIGHT . "\n";# echo $c->GREEN_LIGHT . "\n";
?>
<?php/*** A class that simulates Enums behaviour* <code>* class Season extends Enum{* const Spring = 0;* const Summer = 1;* const Autumn = 2;* const Winter = 3;* }** $currentSeason = new Season(Season::Spring);* $nextYearSeason = new Season(Season::Spring);* $winter = new Season(Season::Winter);* $whatever = new Season(-1); // Throws InvalidArgumentException* echo $currentSeason.is(Season::Spring); // True* echo $currentSeason.getName(); // 'Spring'* echo $currentSeason.is($nextYearSeason); // True* echo $currentSeason.is(Season::Winter); // False* echo $currentSeason.is(Season::Spring); // True* echo $currentSeason.is($winter); // False* </code>** Class Enum** PHP Version 5.5*/abstract class Enum{/*** Will contain all the constants of every enum that gets created to* avoid expensive ReflectionClass usage* @var array*/private static $_constCacheArray = [];/*** The value that separates this instance from the rest of the same class* @var mixed*/private $_value;/*** The label of the Enum instance. Will take the string name of the* constant provided, used for logging and human readable messages* @var string*/private $_name;/*** Creates an enum instance, while makes sure that the value given to the* enum is a valid one** @param mixed $value The value of the current** @throws \InvalidArgumentException*/public final function __construct($value){$constants = self::_getConstants();if (count($constants) !== count(array_unique($constants))) {throw new \InvalidArgumentException('Enums cannot contain duplicate constant values');}if ($name = array_search($value, $constants)) {$this->_value = $value;$this->_name = $name;} else {throw new \InvalidArgumentException('Invalid enum value provided');}}/*** Returns the constant name of the current enum instance** @return string*/public function getName(){return $this->_name;}/*** Returns the value of the current enum instance** @return mixed*/public function getValue(){return $this->_value;}/*** Checks whether this enum instance matches with the provided one.* This function should be used to compare Enums at all times instead* of an identity comparison* <code>* // Assuming EnumObject and EnumObject2 both extend the Enum class* // and constants with such values are defined* $var = new EnumObject('test');* $var2 = new EnumObject('test');* $var3 = new EnumObject2('test');* $var4 = new EnumObject2('test2');* echo $var->is($var2); // true* echo $var->is('test'); // true* echo $var->is($var3); // false* echo $var3->is($var4); // false* </code>** @param mixed|Enum $enum The value we are comparing this enum object against* If the value is instance of the Enum class makes* sure they are instances of the same class as well,* otherwise just ensures they have the same value** @return bool*/public final function is($enum){// If we are comparing enums, just make// sure they have the same toString valueif (is_subclass_of($enum, __CLASS__)) {return get_class($this) === get_class($enum)&& $this->getValue() === $enum->getValue();} else {// Otherwise assume $enum is the value we are comparing against// and do an exact comparisonreturn $this->getValue() === $enum;}}
/*** Returns the constants that are set for the current Enum instance** @return array*/private static function _getConstants(){if (self::$_constCacheArray == null) {self::$_constCacheArray = [];}$calledClass = get_called_class();if (!array_key_exists($calledClass, self::$_constCacheArray)) {$reflect = new \ReflectionClass($calledClass);self::$_constCacheArray[$calledClass] = $reflect->getConstants();}return self::$_constCacheArray[$calledClass];}}
abstract class DaysOfWeekEnum{public function __construct(string $value){$this->value = $value;}public function __toString(){return $this->value;}
}class Monday extends DaysOfWeekEnum{public function __construct(){parent::__construct("Monday");}}
class Tuesday extends DaysOfWeekEnum{public function __construct(){parent::__construct("Tuesday");}}
<?phpclass Month extends SplEnum {const __default = self::January;
const January = 1;const February = 2;const March = 3;const April = 4;const May = 5;const June = 6;const July = 7;const August = 8;const September = 9;const October = 10;const November = 11;const December = 12;}
echo new Month(Month::June) . PHP_EOL;
try {new Month(13);} catch (UnexpectedValueException $uve) {echo $uve->getMessage() . PHP_EOL;}?>
/*** An interface that groups HTTP Accept: header Media Types in one place.*/interface MediaTypes{/*** Now, if you have to use these same constants with another class, you can* without creating funky inheritance / is-a relationships.* Also, this gets around the single inheritance limitation.*/
public const HTML = 'text/html';public const JSON = 'application/json';public const XML = 'application/xml';public const TEXT = 'text/plain';}
/*** An generic request class.*/abstract class Request{// Why not put the constants here?// 1) The logical reuse issue.// 2) Single Inheritance.// 3) Overriding is possible.
// Why put class constants here?// 1) The constant value will not be necessary in other class families.}
/*** An incoming / server-side HTTP request class.*/class HttpRequest extends Request implements MediaTypes{// This class can implement groups of constants as necessary.}
abstract class Enum {protected $val;
protected function __construct($arg) {$this->val = $arg;}
public function __toString() {return $this->val;}
public function __set($arg1, $arg2) {throw new Exception("enum does not have property");}
public function __get($arg1) {throw new Exception("enum does not have property");}
// not really neededpublic function __call($arg1, $arg2) {throw new Exception("enum does not have method");}
// not really neededstatic public function __callStatic($arg1, $arg2) {throw new Exception("enum does not have static method");}}
您的枚举:
final class MyEnum extends Enum {static public function val1() {return new self("val1");}
static public function val2() {return new self("val2");}
static public function val3() {return new self("val3");}}
function travelCost(TransportMode $mode, int $distance): int{ /* implementation */ }
$mode = TransportMode::Boat;
$bikeCost = travelCost(TransportMode::Bicycle, 90);$boatCost = travelCost($mode, 90);
// this one would fail: (Enums are singletons, not scalars)$failCost = travelCost('Car', 90);
class Human{private $gender;
public function __set($key, $value){if($key == 'day' && !in_array($value, array('Man', 'Woman')){new Exception('Wrong value for '.__CLASS__.'->'.$key);}else{$this->$key = $value;}...}}
$enum = BasicEnum::someValue();echo $enum->equals(BasicEnum::someValue()) ? 'true' : 'false'; // trueecho $enum->value; // 'someValue' or the value you have definedecho $enum->label; // 'someValue' or the label you have definedecho $enum; // 'someValue' or the value you have definedecho json_encode($enum); // {"label": "someValue", "value: "someValue" }
枚举定义非常简单(值和标签方法是可选的)
/*** @method static self post()* @method static self about()* @method static self contact()*/class PostType extends BaseEnum{protected static function values(): array{return ['post' => 0,'about' => 1,'contact' => 2];}
protected static function labels(): array{return ['post' => 'Regular posts','about' => 'The about page','contact' => 'The contact page'];}}