Как можно использовать функции, подобные Enum (как указано на Java и других языках высокого уровня) в PHP? Я знаю, что PHP не позволяет вам создавать перечисления в настоящее время, но что может быть самым близким?
Возможно использование const
.
class SomeClass { const FIRSTVAL = 1; const SECONDVAL = 2; };
Я использую константы класса и немного обтекания.
<?php /** * @package Red.Core * @author kris@theredhead.nl * * Implements the abstract base for all enum types * * example of a typical enum: * * class DayOfWeek extends Enum * { * const Sunday = 0; * const Monday = 1; * const Tuesday = 2; * const Wednesday = 3; * const Thursday = 4; * const Friday = 5; * const Saturday = 6; * } * * usage examples: * * $monday = Enum::FromString( 'DayOfWeek::Monday' ); // (int) 1 * $monday = DayOfWeek::Monday // (int) 1 * $monday = Enum::ToString( 'DayOfWeek', DayOfWeek::Monday ); // (string) "DayOfWeek::Monday" * $monday = Enum::Label( 'DayOfWeek', DayOfWeek::Monday ); // (string) "Monday" * **/ abstract class Enum { // make sure there are never any instances created final private function __construct() { throw new Exception( 'Enum and Subclasses cannot be instantiated.' ); } /** * Give the integer associated with the const of the given string in the format of "class:const" * * @param string $string * @return integer */ final public static function FromString( $string ) { if ( strpos( $string, '::' ) < 1 ) { throw new Exception( 'Enum::FromString( $string ) Input string is not in the expected format.' ); } list( $class, $const ) = explode( '::', $string ); if ( class_exists( $class, false ) ) { $reflector = new ReflectionClass( $class ); if ( $reflector->IsSubClassOf( 'Enum' ) ) { if ( $reflector->hasConstant( $const ) ) { return eval( sprintf( 'return %s;', $string ) ); } } } throw new Excption( sprintf( '%s does not map to an Enum field', $string ) ); } final public static function IsValidValue( $enumType, $enumValue ) { if ( class_exists( $enumType ) ) { $reflector = new ReflectionClass( $enumType ); if ( $reflector->IsSubClassOf( 'Enum' ) ) { foreach( $reflector->getConstants() as $label => $value ) { if ( $value == $enumValue ) { return true; } } } } return false; } final public static function IsValidLabel( $enumType, $enumValue ) { if ( class_exists( $enumType ) ) { $reflector = new ReflectionClass( $enumType ); if ( $reflector->IsSubClassOf( 'Enum' ) ) { foreach( $reflector->getConstants() as $label => $value ) { if ( $label == $enumValue ) { return true; } } } } return false; } /** * For a given $enumType, give the complete string representation for the given $enumValue (class::const) * * @param string $enumType * @param integer $enumValue * @return string */ final public static function ToString( $enumType, $enumValue ) { $result = 'NotAnEnum::IllegalValue'; if ( class_exists( $enumType, false ) ) { $reflector = new ReflectionClass( $enumType ); $result = $reflector->getName() . '::IllegalValue'; foreach( $reflector->getConstants() as $key => $val ) { if ( $val == $enumValue ) { $result = str_replace( 'IllegalValue', $key, $result ); break; } } } return $result; } /** * For a given $enumType, give the label associated with the given $enumValue (const name in class definition) * * @param string $enumType * @param integer $enumValue * @return string */ final public static function Label( $enumType, $enumValue ) { $result = 'IllegalValue'; if ( class_exists( $enumType, false ) ) { $reflector = new ReflectionClass( $enumType ); foreach( $reflector->getConstants() as $key => $val ) { if ( $val == $enumValue ) { $result = $key; break; } } } return $result; } } ?>
Это обновленная версия из кода @Kris, чтобы лучше работать с более новыми версиями PHP. Он был составлен на основе комментария @lassombra.
/** * Implements the abstract base for all enum types * @see http://stackoverflow.com/a/2324746/1003020 * @see http://stackoverflow.com/a/254543/1003020 * * Example of a typical enum: * * class DayOfWeek extends Enum * { * const Sunday = 0; * const Monday = 1; * const Tuesday = 2; * const Wednesday = 3; * const Thursday = 4; * const Friday = 5; * const Saturday = 6; * } * * Usage examples: * * $monday = DayOfWeek::Monday // (int) 1 * DayOfWeek::isValidName('Monday') // (bool) true * DayOfWeek::isValidName('monday', $strict = true) // (bool) false * DayOfWeek::isValidValue(0) // (bool) true * DayOfWeek::fromString('Monday') // (int) 1 * DayOfWeek::toString(DayOfWeek::Tuesday) // (string) "Tuesday" * DayOfWeek::toString(5) // (string) "Friday" **/ abstract class Enum { private static $constCacheArray = NULL; 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]; } public static function isValidName($name, $strict = false) { $constants = self::getConstants(); if ($strict) { return array_key_exists($name, $constants); } $keys = array_map('strtolower', array_keys($constants)); return in_array(strtolower($name), $keys); } public static function isValidValue($value, $strict = true) { $values = array_values(self::getConstants()); return in_array($value, $values, $strict); } public static function fromString($name) { if (self::isValidName($name, $strict = true)) { $constants = self::getConstants(); return $constants[$name]; } return false; } public static function toString($value) { if (self::isValidValue($value, $strict = true)) { return array_search($value, self::getConstants()); } return false; } }
Вы также можете использовать это:
class Enum{ private $m_valueName = NULL; private function __construct($valueName){ $this->m_valueName = $valueName; } public static function __callStatic($methodName, $arguments){ $className = get_called_class(); return new $className($methodName); } function __toString(){ return $this->m_valueName; } } class NotificationType extends Enum{ const Notification = NULL; const Warning = NULL; const Error = NULL; } function Test(NotificationType $type){ echo "Test function, type: $type<br>"; } Test(NotificationType::Warning());
Вы можете использовать константы
class myClass { const aValue = 123; const aString = "ABC"; };
Но это не дало бы приятного способа итерации через них, поэтому я бы выбрал подходящий массив, так как было бы проще управлять:
class myClass{ $enum = array ("first" => 123, "second" => "ABC"); }
Существует класс SplEnum
.
Пример использования из документов:
<?php class 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; }
Вышеприведенный пример выводит
6 Value not a const in enum Month
Другая возможность – использовать пакет myclabs / php-enum .
Дешевый трюк заключается в создании массива с возможными значениями. Однако, в отличие от приведенных выше ответов, я бы выбрал массив, в котором пары ключ / значение равны, то есть:
<?php $enum = Array( 'apple' => 'apple', 'pear' => 'pear', 'orange' => 'orange' ); ?>
Таким образом, если ($enum[$value] != $value)
, вы знаете, что указанное значение не входит в набор.
Конечно, если вы хотите, чтобы пары ключ / значение отличались друг от друга, регулярный массив мог бы пойти.
Как массив.
$arr = array('A','B','C','D'); $find = 'A'; $key = array_search($find,$arr); echo $arr[$key];