如何在PHP中使用类似Enum的功能(如Java和其他高级语言中所提供的)?我知道PHP目前不允许你创建枚举,但最接近的是什么?
答案 0 :(得分:12)
或许使用const
。
class SomeClass {
const FIRSTVAL = 1;
const SECONDVAL = 2;
};
答案 1 :(得分:12)
我使用类常量和一些反射技巧。
<?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;
}
}
?>
答案 2 :(得分:8)
这是@Kris代码的更新版本,可以更好地使用较新版本的PHP。它是基于@lassombra评论而制作的。
private void doSomething() {
Socket socket = null;
for (int i = 0; i < 3; i++) {
try {
socket = connectToServer();
break;
} catch (IOException e) {
// Log exception,
// show message to user,
// etc.
}
}
if (socket != null) {
// Ok
} else {
// Could not connect to server.
}
}
private Socket connectToServer() throws IOException {
// Always returns a valid socket.
// Throws exception in case of problems.
}
答案 3 :(得分:4)
你也可以使用这个:
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());
答案 4 :(得分:2)
提供了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包。
答案 5 :(得分:1)
您可以使用常量
class myClass {
const aValue = 123;
const aString = "ABC";
};
但它不会提供一种很好的迭代方法,所以我可能会选择一个关联数组,因为它更容易管理:
class myClass{
$enum = array ("first" => 123,
"second" => "ABC");
}
答案 6 :(得分:0)
作为阵列。
$arr = array('A','B','C','D');
$find = 'A';
$key = array_search($find,$arr);
echo $arr[$key];
答案 7 :(得分:0)
一个便宜的技巧是创建一个具有可能值的数组。但是,与上述答案不同,我选择一个键/值对相等的数组,即:
<?php
$enum = Array(
'apple' => 'apple',
'pear' => 'pear',
'orange' => 'orange'
);
?>
这样,如果($enum[$value] != $value)
,您知道给定的值不在集合中。
当然,如果你想要键/值对不同,那么常规阵列就是你的选择。
答案 8 :(得分:0)
就我而言,我需要存储在整个应用程序中使用的权限名称。我最后得到了一个基本的枚举抽象类,该类为枚举定义了几个实用程序函数,然后对其进行了扩展。这是基本的枚举类:
EventSource = ’Customer’
and EventName = ‘Login’
and EventType = ’ForgotEmail’
and StatusDetail = ‘Screen:AboutYou _NextButton;Zip:<>’
___ AND __
EventSource = ’Customer’
EventName = ’Login’
and EventType = ’ForgotEmail’
and StatusDetail = ’Status: Status:RetrieveEmailSuccessful
以下是通过扩展抽象类创建的示例枚举:
SELECT
ab.TransactionDate,
SUM(CASE WHEN EventSource = 'Customer' AND EventName = 'Login' AND EventType = 'Standard' AND StatusDesc = 'Success'
THEN 1 ELSE 0 END) AS TotalLogin#,
SUM(CASE WHEN EventSource = 'Customer' AND EventName = 'Login' AND EventType = 'ForgotEmail'
THEN 1 ELSE 0 END) AS Abandon#
FROM
(SELECT
p.TransactionDate, p.PolicyNumber, p.UserId,
p.CustomerBrand, p.EventSource, p.EventName, p.EventType,
p.Status, p.StatusDetail, p.StatusDesc,
ROW_NUMBER() OVER (PARTITION BY p.PolicyNumber ORDER BY p.TransactionDate) AS row_count_policy,
ROW_NUMBER() OVER (PARTITION BY p.UserId ORDER BY p.TransactionDate) AS row_count_user_id
FROM
[iso_report].[dbo].[PACE_Service_Log_support] p WITH (nolock)
WHERE
ISNULL(EventSource, '') IN ('Customer')
AND ISNULL(EventName, '') IN ('Login')
AND CAST(Transactiondate AS DATE) BETWEEN '2017-01-01' AND '2017-1-1') ab
GROUP BY
ab.TransactionDate
<?php
namespace App\Enums;
use ReflectionClass;
abstract class BasicEnum {
private static $constCacheArray = NULL;
public 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);
}
}
这是Permissions枚举的示例用法:
<?php
namespace App\Enums;
class Permissions extends BasicEnum
{
const COMMENTS_CREATE = 'create comments';
const COMMENTS_VIEW = 'view comments';
const COMMENTS_EDIT = 'edit comments';
const COMMENTS_DELETE = 'delete comments';
const COMMENTS_RESTORE = 'restore comments';
const REACTIONS_CREATE = 'create reactions';
const REACTIONS_VIEW = 'view reactions';
const REACTIONS_EDIT = 'edit reactions';
const REACTIONS_DELETE = 'delete reactions';
const REACTIONS_RESTORE = 'restore reactions';
const QUESTIONS_CREATE = 'create questions';
const QUESTIONS_VIEW = 'view questions';
const QUESTIONS_EDIT = 'edit questions';
const QUESTIONS_DELETE = 'delete questions';
const QUESTIONS_RESTORE = 'restore questions';
const PERMISSIONS_CREATE = 'create permissions';
const PERMISSIONS_VIEW = 'view permissions';
const PERMISSIONS_EDIT = 'edit permissions';
const PERMISSIONS_DELETE = 'delete permissions';
const PERMISSIONS_RESTORE = 'restore permissions';
}
希望这会有所帮助。