How can Enum-like functionality (as provided in Java and other high level languages) be used in PHP? I know PHP doesn't allow you to create enums currently, but what's the closest one could get?
如何在PHP中使用类似Enum的功能(如Java和其他高级语言中所提供的)?我知道PHP目前不允许你创建枚举,但最接近的是什么?
8 个解决方案
#1
11
Using const
, perhaps.
或许使用const。
class SomeClass {
const FIRSTVAL = 1;
const SECONDVAL = 2;
};
#2
10
I use class constants, and a bit of reflection trickery.
我使用类常量和一些反射技巧。
<?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;
}
}
?>
#3
8
This is an updated version from the @Kris code, to work better with newer versions of PHP. It was made based on @lassombra comment.
这是@Kris代码的更新版本,可以更好地使用较新版本的PHP。它是基于@lassombra评论制作的。
/**
* Implements the abstract base for all enum types
* @see http://*.com/a/2324746/1003020
* @see http://*.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;
}
}
#4
4
You may also use this one:
你也可以用这个:
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());
#5
2
There is an SplEnum
class provided.
提供了SplEnum类。
Sample usage from the docs:
来自文档的示例用法:
<?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;
}
The above example will output
上面的例子将输出
6
Value not a const in enum Month
Another possibility is to use the myclabs/php-enum package.
另一种可能性是使用myclabs / php-enum包。
#6
1
You could use constants
你可以使用常量
class myClass {
const aValue = 123;
const aString = "ABC";
};
But it wouldn't give a nice way of iterating through them so i would probably opt for an associate array as it would be easier to manage:
但它不会提供一种很好的迭代方式,所以我可能会选择一个关联数组,因为它更容易管理:
class myClass{
$enum = array ("first" => 123,
"second" => "ABC");
}
#7
0
A cheap trick is to create an array with possible values. However, unlike the above answers, I'd opt for an array where key/value pairs are equal, i.e.:
一个便宜的技巧是创建一个具有可能值的数组。但是,与上面的答案不同,我会选择一个键/值对相等的数组,即:
<?php
$enum = Array(
'apple' => 'apple',
'pear' => 'pear',
'orange' => 'orange'
);
?>
That way, if ($enum[$value] != $value)
, you know the value given is not in the set.
这样,如果($ enum [$ value]!= $ value),您知道给定的值不在集合中。
Ofcourse, if you want the key/value pairs to be different, a regular array would be the way to go.
当然,如果你想要键/值对不同,那么常规阵列就是你要走的路。
#8
0
As an array.
作为阵列。
$arr = array('A','B','C','D');
$find = 'A';
$key = array_search($find,$arr);
echo $arr[$key];
#1
11
Using const
, perhaps.
或许使用const。
class SomeClass {
const FIRSTVAL = 1;
const SECONDVAL = 2;
};
#2
10
I use class constants, and a bit of reflection trickery.
我使用类常量和一些反射技巧。
<?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;
}
}
?>
#3
8
This is an updated version from the @Kris code, to work better with newer versions of PHP. It was made based on @lassombra comment.
这是@Kris代码的更新版本,可以更好地使用较新版本的PHP。它是基于@lassombra评论制作的。
/**
* Implements the abstract base for all enum types
* @see http://*.com/a/2324746/1003020
* @see http://*.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;
}
}
#4
4
You may also use this one:
你也可以用这个:
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());
#5
2
There is an SplEnum
class provided.
提供了SplEnum类。
Sample usage from the docs:
来自文档的示例用法:
<?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;
}
The above example will output
上面的例子将输出
6
Value not a const in enum Month
Another possibility is to use the myclabs/php-enum package.
另一种可能性是使用myclabs / php-enum包。
#6
1
You could use constants
你可以使用常量
class myClass {
const aValue = 123;
const aString = "ABC";
};
But it wouldn't give a nice way of iterating through them so i would probably opt for an associate array as it would be easier to manage:
但它不会提供一种很好的迭代方式,所以我可能会选择一个关联数组,因为它更容易管理:
class myClass{
$enum = array ("first" => 123,
"second" => "ABC");
}
#7
0
A cheap trick is to create an array with possible values. However, unlike the above answers, I'd opt for an array where key/value pairs are equal, i.e.:
一个便宜的技巧是创建一个具有可能值的数组。但是,与上面的答案不同,我会选择一个键/值对相等的数组,即:
<?php
$enum = Array(
'apple' => 'apple',
'pear' => 'pear',
'orange' => 'orange'
);
?>
That way, if ($enum[$value] != $value)
, you know the value given is not in the set.
这样,如果($ enum [$ value]!= $ value),您知道给定的值不在集合中。
Ofcourse, if you want the key/value pairs to be different, a regular array would be the way to go.
当然,如果你想要键/值对不同,那么常规阵列就是你要走的路。
#8
0
As an array.
作为阵列。
$arr = array('A','B','C','D');
$find = 'A';
$key = array_search($find,$arr);
echo $arr[$key];