¿Puedo obtener los CONST definidos en una clase PHP?

140

Tengo varios CONST definidos en algunas clases y quiero obtener una lista de ellos. Por ejemplo:

class Profile {
    const LABEL_FIRST_NAME = "First Name";
    const LABEL_LAST_NAME = "Last Name";
    const LABEL_COMPANY_NAME = "Company";
}

¿Hay alguna forma de obtener una lista de los CONST definidos en la Profileclase? Por lo que puedo decir, la opción más cercana ( get_defined_constants()) no funcionará.

Lo que realmente necesito es una lista de los nombres constantes, algo como esto:

array('LABEL_FIRST_NAME',
    'LABEL_LAST_NAME',
    'LABEL_COMPANY_NAME')

O:

array('Profile::LABEL_FIRST_NAME', 
    'Profile::LABEL_LAST_NAME',
    'Profile::LABEL_COMPANY_NAME')

O incluso:

array('Profile::LABEL_FIRST_NAME'=>'First Name', 
    'Profile::LABEL_LAST_NAME'=>'Last Name',
    'Profile::LABEL_COMPANY_NAME'=>'Company')
Brock Boland
fuente
Puedes hacer esto usando la reflexión . Busque "Imprimir constantes de clase" en esa página para ver un ejemplo.
n3rd
Usando Reflection, y ReflectionClass en Cl, puedes usar la función getConstants nz.php.net/manual/en/class.reflectionclass.php
Tim Ebenezer

Respuestas:

245

Puedes usar Reflection para esto. Tenga en cuenta que si está haciendo esto mucho, es posible que desee ver el resultado en caché.

<?php
class Profile {
    const LABEL_FIRST_NAME = "First Name";
    const LABEL_LAST_NAME = "Last Name";
    const LABEL_COMPANY_NAME = "Company";
}


$refl = new ReflectionClass('Profile');
print_r($refl->getConstants());

Salida:

Array
(
    'LABEL_FIRST_NAME' => 'First Name',
    'LABEL_LAST_NAME' => 'Last Name',
    'LABEL_COMPANY_NAME' => 'Company'
)
Tom Haigh
fuente
44
Dos NB menores: primero, en 5.3, Profilepueden usarse como argumento para el constructor del reflector, sin comillas (un nombre de clase simple); segundo, para ser completamente claros, las claves de la matriz resultante son cadenas, no constantes, ya que el formato aquí podría tomarse para sugerir. (Vale la pena mencionarlo solo porque el fn no está documentado .)
Benji XVI,
11
@Benji XVI En 5.3, si tiene avisos activados, no podrá usarlos Profilesin las comillas, ya que mostrará el siguiente error: Aviso: Uso de perfil constante indefinido - supuesto 'Perfil'. Así que sugiero mantener las citas'Profile'
toneplex
10
Es bueno definir la lógica relacionada con las constantes dentro de la clase, por lo que no necesita codificar el argumento del constructor sino utilizarlo __CLASS__.
Luke Adamczewski
77
new ReflectionClass(Profile::class)funciona bien también
mtizziani
@mtizziani cierto, ¡pero ten en cuenta los espacios de nombres! Digamos que tiene un espacio de nombres Citycon clase B: B::classfuncionaría bien, pero si los usara, por ejemplo, en el espacio de nombres Jungle, llamar B::classallí sin incluirlo usedaría como resultado Jungle\B(¡aunque Jungle NO tenga B en absoluto!)
jave.web
22

Esta

 $reflector = new ReflectionClass('Status');
 var_dump($reflector->getConstants());
Wrikken
fuente
1
+1 Esto sería todo, ya que no puedo encontrar ninguna función PHP de procedimiento incorporada para obtener constantes de clase, lo cual es un poco vergonzoso.
BoltClock
1
Probablemente porque hay poca necesidad de ello. El OP puede querer hacer una metaconfiguración estableciendo typescomo all constants this class has, lo que en la mayoría de los casos, y en mi opinión limitada, probablemente sea mejor con herencia o una variable de matriz estática con los tipos (dejando espacio para constantes con otros significados / utilizar).
Escrito el
16

Use token_get_all () . A saber:

<?php
header('Content-Type: text/plain');

$file = file_get_contents('Profile.php');
$tokens = token_get_all($file);

$const = false;
$name = '';
$constants = array();
foreach ($tokens as $token) {
    if (is_array($token)) {
        if ($token[0] != T_WHITESPACE) {
            if ($token[0] == T_CONST && $token[1] == 'const') {
                $const = true;
                $name = '';
            } else if ($token[0] == T_STRING && $const) {
                $const = false;
                $name = $token[1];
            } else if ($token[0] == T_CONSTANT_ENCAPSED_STRING && $name) {
                $constants[$name] = $token[1];
                $name = '';
            }
        }
    } else if ($token != '=') {
        $const = false;
        $name = '';
    }
}

foreach ($constants as $constant => $value) {
    echo "$constant = $value\n";
}
?>

Salida:

LABEL_FIRST_NAME = "First Name"
LABEL_LAST_NAME = "Last Name"
LABEL_COMPANY_NAME = "Company"
cletus
fuente
1
+1, aunque diría que este es un excelente momento para usar Reflection como lo mencionan otros carteles, también es importante comprender el funcionamiento "bajo el capó" y poder prescindir de ellos o replicarlos si es necesario. Buen espectaculo.
Publicado el
1
Si no desea que su clase se cargue en la memoria, token_get_all es una alternativa fantástica. Es MUCHO más rápido que Reflection y no satura la memoria del proceso si necesita hacer esto con muchas clases.
Harold
¡+1 para la solución basada en token! Comprender el análisis basado en tokens es un placer teniendo en cuenta el rendimiento ... y, como siempre, hay una gran persona que muestra cómo analizar constantes a través de token_get_all (). ¡Muchas gracias!
mwatzer
Presumiblemente, esto actúa solo en el archivo único y no hereda ninguna constante de las clases primarias. De hecho, esta técnica ni siquiera se preocupa por la clase: le dará todas las constantes en el archivo, incluso en el ámbito global. Sin embargo, es una gran herramienta para explorar.
Jason
14

En PHP5 puede usar Reflection: (referencia manual)

$class = new ReflectionClass('Profile');
$consts = $class->getConstants();
Parsingphase
fuente
13

Según los comentarios de los documentos de PHP, si puede usar ReflectionClass (PHP 5):

function GetClassConstants($sClassName) {
    $oClass = new ReflectionClass($sClassName);
    return $oClass->getConstants();
}

La fuente está aquí.

mway
fuente
9

Usa ReflectionClass y getConstants()da exactamente lo que quieres:

<?php
class Cl {
    const AAA = 1;
    const BBB = 2;
}
$r = new ReflectionClass('Cl');
print_r($r->getConstants());

Salida:

Array
(
    [AAA] => 1
    [BBB] => 2
)
Ben James
fuente
6

Rasgo con método estático - al rescate

Parece que es un buen lugar para usar Rasgos con una función estática para extender la funcionalidad de la clase. Los rasgos también nos permitirán implementar esta funcionalidad en cualquier otra clase sin tener que volver a escribir el mismo código una y otra vez (manténgase SECO).

Utilice nuestro rasgo personalizado 'ConstantExport' con en la clase de perfil. Hazlo para cada clase que necesites esta funcionalidad.

/**
 * ConstantExport Trait implements getConstants() method which allows 
 * to return class constant as an assosiative array
 */
Trait ConstantExport 
{
    /**
     * @return [const_name => 'value', ...]
     */
    static function getConstants(){
        $refl = new \ReflectionClass(__CLASS__);
        return $refl->getConstants();
    }
}

Class Profile 
{
    const LABEL_FIRST_NAME = "First Name";
    const LABEL_LAST_NAME = "Last Name";
    const LABEL_COMPANY_NAME = "Company";

    use ConstantExport;

}

EJEMPLO DE USO

// So simple and so clean
$constList = Profile::getConstants(); 

print_r($constList); // TEST

SALIDAS:

Array
(
    [LABEL_FIRST_NAME] => First Name
    [LABEL_LAST_NAME] => Last Name
    [LABEL_COMPANY_NAME] => Company
)
DevWL
fuente
5

Sí, usas la reflexión . Mira la salida de

<?
Reflection::export(new ReflectionClass('YourClass'));
?>

Eso debería darte una idea de lo que verás.

caos
fuente
4

Es útil tener un método dentro de la clase para devolver sus propias constantes.
Puedes hacerlo de esta manera:

class Profile {
    const LABEL_FIRST_NAME = "First Name";
    const LABEL_LAST_NAME = "Last Name";
    const LABEL_COMPANY_NAME = "Company";


    public static function getAllConsts() {
        return (new ReflectionClass(get_class()))->getConstants();
    }
}

// test
print_r(Profile::getAllConsts());
Luis Siquot
fuente
3

¿Por qué no ponerlos en una variable de clase como una matriz para empezar? Facilita el bucle.

private $_data = array("production"=>0 ...);
Detectar
fuente
2
¿Porque las matrices no son constantes? Si implementa algo que se supone que es una constante como variable, entonces corre el riesgo de que se modifique o desactive accidentalmente. En otras palabras, no puede depender de que permanezcan constantes.
GordonM
3

Eventualmente con espacios de nombres:

namespaces enums;
class enumCountries 
{
  const CountryAustria          = 1 ;
  const CountrySweden           = 24;
  const CountryUnitedKingdom    = 25;
}

namespace Helpers;
class Helpers
{
  static function getCountries()
  {
    $c = new \ReflectionClass('\enums\enumCountries');
    return $c->getConstants();
  }
}

print_r(\Helpers\Helpers::getCountries());
revocar
fuente
1
class Qwerty 
{
    const __COOKIE_LANG_NAME__ = "zxc";
    const __UPDATE_COOKIE__ = 30000;

    // [1]
    public function getConstants_(){

        return ['__COOKIE_LANG_NAME__' => self::__COOKIE_LANG_NAME__, 
                '__UPDATE_COOKIE__' => self::__UPDATE_COOKIE__]; 
    }    

    // [2]
    static function getConstantsStatic_(){

        return ['__COOKIE_LANG_NAME__' => self::__COOKIE_LANG_NAME__, 
                '__UPDATE_COOKIE__' => self::__UPDATE_COOKIE__]; 
    } 
}

// [1]
$objC = new Qwerty();
var_dump($objC->getConstants_());

// [2]
var_dump(Qwerty::getConstantsStatic_());
Юрий Светлов
fuente