Question

I have several CONST's defined on some classes, and want to get a list of them. For example:

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

Is there any way to get a list of the CONST's defined on the Profile class? As far as I can tell, the closest option(get_defined_constants()) won't do the trick.

What I actually need is a list of the constant names - something like this:

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

Or:

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

Or even:

array('Profile::LABEL_FIRST_NAME'=>'First Name', 
    'Profile::LABEL_LAST_NAME'=>'Last Name',
    'Profile::LABEL_COMPANY_NAME'=>'Company')
Was it helpful?

Solution

You can use Reflection for this. Note that if you are doing this a lot you may want to looking at caching the result.

<?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());

Output:

Array
(
    'LABEL_FIRST_NAME' => 'First Name',
    'LABEL_LAST_NAME' => 'Last Name',
    'LABEL_COMPANY_NAME' => 'Company'
)

OTHER TIPS

This

 $reflector = new ReflectionClass('Status');
 var_dump($reflector->getConstants());

Use token_get_all(). Namely:

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

Output:

LABEL_FIRST_NAME = "First Name"
LABEL_LAST_NAME = "Last Name"
LABEL_COMPANY_NAME = "Company"

In PHP5 you can use Reflection: (manual reference)

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

Per the PHP docs comments, if you're able to use the ReflectionClass (PHP 5):

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

Source is here.

Using ReflectionClass and getConstants() gives exactly what you want:

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

Output:

Array
(
    [AAA] => 1
    [BBB] => 2
)

Yeah, you use reflection. Look at the output of

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

That should give you the idea of what you'll be looking at.

It is handy to have a method inside the class to return its own constants.
You can do this way:

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());

Trait with static method - to the rescue

Looks like it is a nice place to use Traits with a static function to extend class functionality. Traits will also let us implement this functionality in any other class without rewriting the same code over and over again (stay DRY).

Use our custom 'ConstantExport' Trait with in Profile class. Do it for every class that you need this functionality.

/**
 * 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;

}

USE EXAMPLE

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

print_r($constList); // TEST

OUTPUTS:

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

Why not put them in a class variable as an array to begin with? Makes it easier to loop thru.

private $_data = array("production"=>0 ...);

Eventually with namespaces:

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());
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_());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top