2009-12-10 19 views

Respuesta

48

Usted puede obtener con el reflection API

Asumo que le gustaría obtener el nombre de la constante basado en el valor de la variable (valor de valor == variable constante). Obtenga todas las constantes definidas en la clase, bucleelas y compare los valores de esas constantes con el valor de su variable. Tenga en cuenta que con este enfoque puede obtener alguna otra constante que la que desea, si hay dos constantes con el mismo valor.

ejemplo:

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; 
    } 
} 

PD: Te importa decirle qué necesita esto, ya que parece muy raro ...

+1

nada serio, en realidad. Solo estoy pensando en la forma de pasar el código de error de la función de clase. En cuanto a mí, const ERR_SOME_ERROR = 'ERR_SOME_ERROR' parece extraño, pensé que mi función getLastError() podría devolver algo como array (5003 => 'ERR_SOME_ERROR', 5002 => 'ERR_SOME_ERR2') y así sucesivamente. Solo para que se devuelva el código de error y el nombre del error. Bueno, cuanto más lo pienso, probablemente no lo use (por la sintaxis inusual que me dijiste) :) –

+0

también lo necesitaba para CURLE_ * soporte constante donde 'curl_multi_strerror' no estaba disponible –

+2

" necesito "algo así para proporcionar un mejor resultado de error sin tener que volver a escribir cómo rastreamos ciertos códigos de error que se almacenan como constantes. – Frug

12

Con Reflexión:

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

$constants es una matriz que contiene todos los nombres y valores de las constantes definidas en la clase Foo.

1

Todas las constantes se pueden asignar a una matriz con esta función.

$const = get_defined_constants(); 

a continuación, utilizando la función siguiente puede imprimir la estructura matriz

echo "<pre>"; 

print_r($const); 

y se puede ver una explicación más detallada aquí www.sugunan.com

20

Aquí es lo que hice para lograrlo. Inspirado por 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]; 
    } 
} 
+3

Solo quiero decir que esto no funcionará si las constantes tienen el mismo valor. No debería ser un problema la mayor parte del tiempo, pero sí ... – Populus

7

Sé que esta es una vieja pregunta y todo, pero todavía siento que tengo alguna entrada útil. Implementé esto usando una clase abstracta que extienden todas mis enumeraciones. La clase abstracta contiene un método genérico 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; 
} 

esta manera se puede obtener una cadena legible por humanos para su uso en la producción, en cada enumeración que se extiende la enumeración de base. Además, su implementación de la enumeración, que es final, no se puede extender y, dado que el constructor en el BaseEnum es private, nunca se puede crear una instancia.

Así, por ejemplo, si muestra una lista de todos los nombres de usuario con sus tipos que puede hacer algo como

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

si usted necesita para obtener el valor constante en un procedimiento de la misma clase, sólo tiene para usar el auto operador. Puede usar el reflejo si desea usar las constantes en otra clase

class Foo { 
    const ERR_SOME_CONST = 6001; 

    function bar() { 
     self::ERR_SOME_CONST; 
    } 
} 
3

Advertencia: De esta forma NO debe programar ...(Si usted no está seguro de lo que estás haciendo :))

escribí 1 fila, que hace eco constantes y sus valores numéricos por su elección de CATEGORY_

así que aquí es la lista de 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; 

Y si quieres sólo el que usted está buscando por número => creé 1row función:

//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.";} 

Así, por ejemplo som e constante con el número 64 Info: salida

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

voluntad algo como: NameOfConstant: INFO_LICENSE

5

Todas las otras respuestas cubren los puntos esenciales. Pero, si loca los trazadores de líneas es su cosa, entonces:

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

Si usted necesita para manejar el caso en que el valor no podría ser en realidad una de las constantes, entonces se puede renunciar a una línea adicional:

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

Esta es una solución fácil y rápida. Da la vuelta a la matriz y busca la clave. –

2

OK, OK, ya sé que todo está cubierto :) Pero Jan Hančič pidió caso de uso, así que compartiré el mío. Aparte: todo el mundo parece usar array_flip(). ¿Por qué no array_search()?

Lo necesitaba en una clase que se extiende \ Exception y es una clase base de un conjunto pequeño de mis excepciones concretas. Cada una de esas clases de excepción concretas cubre un amplio dominio de excepción y ha definido varias causas de excepción precisas. ¿Razón? No quiero tener una horda de excepciones para mantener y recordar. Además, existe un conjunto de controladores de excepción que vuelca las agallas de la excepción en el archivo de registro, y es aquí donde necesito obtener el nombre constante como tratar de descifrar la causa de la excepción del estado en bastante doloroso.

Ejemplos de secuencias de comandos de la CLI: mis

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()); 
}); 
Cuestiones relacionadas