【问题标题】:How to get name of the constant?如何获取常量的名称?
【发布时间】:2010-12-25 04:59:23
【问题描述】:

假设你在一个类中定义了一个常量:

class Foo {
    const ERR_SOME_CONST = 6001;

    function bar() {
        $x = 6001;
        // need to get 'ERR_SOME_CONST'
    }
}

PHP 可以吗?

【问题讨论】:

    标签: php class constants


    【解决方案1】:
    class OrderStatus
    {
        public const PENDING = 1;
        public const PROCESSED  = 2;
    
        public static function getStatusCode($value)
        {
            $class = new ReflectionClass(__CLASS__);
            $constants = array_flip($class->getConstants());
    
            return $constants[$value] ?? null;
        }
    
        // OrderStatus::getStatusCode(1); // 'PENDING'
    
    }
    

    【讨论】:

      【解决方案2】:

      所有常量都可以使用这个函数赋值给一个数组。

      $const = get_defined_constants();
      

      然后使用以下函数可以打印数组结构

      echo "<pre>";
      
      print_r($const);
      

      你可以在这里看到更多的解释www.sugunan.com

      【讨论】:

        【解决方案3】:

        好的,好的,我知道一切都已经涵盖了:) 但是 Jan Hančič 要求用例,所以我将分享我的。 另外:似乎每个人都使用 array_flip()。为什么不使用 array_search()?

        我在一个扩展 \Exception 的类中需要它,它是我的一小部分具体异常的基类。这些具体的异常类中的每一个都涵盖了广泛的异常域,并定义了几个精确的异常原因。原因?我不想有一大堆例外需要维护和记住。此外,还有一个异常处理程序集,可以将异常的内容转储到日志文件中 - 我需要在这里获取常量名称,因为我试图从状态中解读异常原因非常痛苦。

        来自我的 CLI 脚本的示例:

        class AbstractException extends Exception {
            public function getName() {
                return array_search($this->getCode(), (new ReflectionClass($this))->getConstants());
            }
        }
        
        class SyntaxException extends AbstractException {
            const BAD_SYNTAX = 90;
            const REQUIRED_PARAM = 91;
            const REQUIRED_VALUE = 92;
            const VALUE_TYPE = 93;
            const VALUE_OUT_OF_BOUNDS = 94;
        
            public function __construct ($message = "", $code = self::BAD_SYNTAX, Exception $previous = NULL) {
                $script = basename($GLOBALS['argv'][0]);
        
                echo "Invalid syntax: $message \nSee: `$script --help` for more information\n";
                parent::__construct($message, $code, $previous);
            }
        }
        
        // in autoload include
        set_exception_handler(function(Exception $e) {
            error_log(basename($GLOBALS['argv'][0]) . ';'. date('Y-m-d H:i:s') .';'. $e->getName() .';'. $e->getMessage() .';'. $e->getFile() .';'. $e->getLine() ."\n", 3, 'error.log');
            exit ($e->getCode());
        });
        

        【讨论】:

          【解决方案4】:

          所有其他答案都涵盖了要点。但是,如果你喜欢疯狂的一个班轮,那么:

          function getConstantName($class, $value)
          {
              return array_flip((new \ReflectionClass($class))->getConstants())[$value];
          }
          

          如果您需要处理值实际上可能不是常量之一的情况,那么您可以放弃额外的一行:

          function getConstantName($class, $value)
          {
              $map = array_flip((new \ReflectionClass($class))->getConstants());
              return (array_key_exists($value, $map) ? $map[$value] : null);
          }
          

          【讨论】:

          • 这是简单快捷的解决方案。翻转数组并检查密钥。
          【解决方案5】:

          这是我为实现它所做的。灵感来自 Jan Hancic。

          class ErrorCode
          {
              const COMMENT_NEWCOMMENT_DISABLED = -4;
              const COMMENT_TIMEBETWEENPOST_ERROR = -3;
              /**
               * Get error message of a value. It's actually the constant's name
               * @param integer $value
               * 
               * @return string
               */
              public static function getErrorMessage($value)
              {
                  $class = new ReflectionClass(__CLASS__);
                  $constants = array_flip($class->getConstants());
          
                  return $constants[$value];
              }
          }
          

          【讨论】:

          • 只想说,如果常量具有相同的值,这将不起作用。大多数时候不应该是一个问题,但是是的......
          • 我认为当常量也具有数组作为值时,这将不起作用..
          【解决方案6】:

          警告:这样你不应该编程......(如果你不确定你在做什么:))

          我写了 1 行,通过您选择的 CATEGORY_ 来回显常量及其数值

          所以这里是 CATEGORY_ERR_ 的列表

          foreach(get_defined_constants() as $key => $value) if(strlen($key)>5) if(substr($key, 0,5)=="ERR_") echo"<br>Found an php ERR_ constant! : ".$key."=>".$value;
          

          如果您只想要按数字查找的那个 => 我创建了 1row 函数:

          //input parameters: CATEGORYNAME_ , #constantNumber
          function getConstantName($category,$constantNumber){foreach(get_defined_constants() as $key => $value) if(strlen($key)>strlen($category)) if(substr($key, 0,strlen($category))==$category) if($value==$constantNumber) return $key; return "No constant found.";}
          

          例如,一些编号为 64 的信息常量:

          echo "NameOfConstant: ".getConstantName("INFO_",64);
          

          将输出类似:NameOfConstant: INFO_LICENSE

          【讨论】:

            【解决方案7】:

            如果你需要获取同一个类的方法的常量值,你只需要使用 self 操作符。如果你想在另一个类上使用常量,你可以使用反射

            class Foo {
                const ERR_SOME_CONST = 6001;
            
                function bar() {
                    self::ERR_SOME_CONST;
                }
            }
            

            【讨论】:

            • 这不是 OP 要求的。
            【解决方案8】:

            我知道这是一个老问题,但我仍然觉得我有一些有用的意见。我使用我所有的枚举都扩展的抽象类来实现这一点。抽象类包含一个通用的 toString() 方法;

            abstract class BaseEnum{
                private final function __construct(){ }
            
                public static function toString($val){
                    $tmp = new ReflectionClass(get_called_class());
                    $a = $tmp->getConstants();
                    $b = array_flip($a);
            
                    return ucfirst(strtolower($b[$val]));
                }
            }
            
            //actual enum
            final class UserType extends BaseEnum {
                const ADMIN = 10;
                const USER = 5;
                const VIEWER = 0;
            }
            

            通过这种方式,您可以在扩展基本枚举的每个枚举上获取人类可读的字符串以在输出中使用。此外,您的枚举实现,即final,不能扩展,因为BaseEnum 中的构造函数是private,它永远不能被实例化。

            例如,如果您显示所有用户名及其类型的列表,您可以执行类似的操作

            foreach($users as $user){
                echo "<li>{$user->name}, ".UserType::toString($user->usertype)."</li>";
            }
            

            【讨论】:

              【解决方案9】:

              您可以通过reflection API 获取它们

              我假设您想根据变量的值(变量的值 == 常量的值)获取常量的名称。获取类中定义的所有常量,遍历它们并将这些常量的值与变量的值进行比较。 请注意,使用这种方法,如果有两个具有相同值的常量,您可能会得到您想要的其他常量。

              示例:

              class Foo {
                  const ERR_SOME_CONST = 6001;
                  const ERR_SOME_OTHER_CONST = 5001;
              
                  function bar() {
                      $x = 6001;
                      $fooClass = new ReflectionClass ( 'Foo' );
                      $constants = $fooClass->getConstants();
              
                      $constName = null;
                      foreach ( $constants as $name => $value )
                      {
                          if ( $value == $x )
                          {
                              $constName = $name;
                              break;
                          }
                      }
              
                      echo $constName;
                  }
              }
              

              ps:你介意说出你为什么需要这个,因为它看起来很不寻常......

              【讨论】:

              • 其实没什么大不了的。只是想从类函数中传递错误代码的方式。至于我 const ERR_SOME_ERROR='ERR_SOME_ERROR' 看起来很奇怪,我认为我的 getLastError() 函数可以返回类似 array(5003=>'ERR_SOME_ERROR',5002=>'ERR_SOME_ERR2') 之类的东西。只是为了返回错误代码和错误名称。好吧,我想得越多,我可能就不会使用它(因为您所说的不寻常的语法):)
              • curl_multi_strerror 不可用的情况下也需要它来获得 CURLE_* 持续支持
              • 我“需要”这样的东西,以便提供更好的错误输出,而不必重写我们如何跟踪存储为常量的某些错误代码。
              【解决方案10】:

              带反射:

              $class = new ReflectionClass("Foo");
              $constants = $class->getConstants();
              

              $constants 是一个数组,其中包含 Foo 类中定义的所有常量的名称和值。

              【讨论】:

                猜你喜欢
                • 2016-02-02
                • 1970-01-01
                • 1970-01-01
                • 2011-02-20
                • 2023-03-24
                • 1970-01-01
                • 1970-01-01
                • 2013-09-16
                相关资源
                最近更新 更多