我可以在PHP类上获取CONST的定义吗?


140

我在某些类上定义了几个CONST,并希望获得它们的列表。例如:

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

有什么方法可以获取在Profile类中定义的CONST的列表吗?据我所知,最接近的option(get_defined_constants())不能解决问题。

我真正需要的是常量名称列表-像这样:

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

要么:

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

甚至:

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

您可以使用反射来做到这一点。在该页面上搜索“打印类常量”以查看示例。
09年

使用Reflection和Cl上的ReflectionClass,可以使用函数getConstants nz.php.net/manual/en/class.reflectionclass.php
Tim Ebenezer,2009年

Answers:


245

您可以为此使用反射。请注意,如果您经常这样做,则可能需要查看缓存结果。

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

输出:

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

4
两个较小的NB:首先,在5.3中,Profile可以用作反射器构造函数的参数,不带引号(简单的类名);其次,要完全清楚,结果数组的键是字符串,而不是常量,因为这里的格式可能会建议这样做。(值得一提的是,fn 没有记录。)
Benji XVI

11
@Benji XVI在5.3中,如果打开了通知,将无法使用Profile引号,因为它将显示以下错误:注意:使用未定义的常量Profile-假定为“ Profile”。因此,我建议保留报价'Profile'
toneplex 2011年

10
最好在类内部定义与常量相关的逻辑,因此您无需对构造函数参数进行硬编码,而应使用__CLASS__
Luke Adamczewski 2013年

7
new ReflectionClass(Profile::class)工作也很好
mtizziani

@mtizziani是真的,但是要注意名称空间!假设您有一个City带有类的 名称空间B- B::class可以正常工作,但是如果您在例如名称空间中使用它们Jungle-调用B::class它而不包含它use会导致Jungle\B(即使Jungle根本没有B!)
jave.web

22

这个

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

1
+1就是这样,因为我找不到用于获取类常量的任何内置过程PHP函数,这有点可惜。
BoltClock

1
可能是因为几乎不需要它。OP可能希望通过设置types为as 来进行元配置all constants this class has,在大多数情况下,按照我的有限观点,在继承或静态数组变量中使用类型可能会更好(为具有其他含义的常量留出空间/用)。
2010年

16

使用token_get_all()。即:

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

输出:

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

1
+1,尽管我会说这是使用其他海报所提到的Reflection的绝佳时机,但是了解“幕后工作”的工作原理并能够在没有它们的情况下进行工作或在必要时进行复制也很重要。不错的演出。
09年

1
如果您不希望将类加载到内存中,那么token_get_all是一个不错的选择。它比Reflection快得多,并且如果您需要使用很多类来做到这一点,则不会使进程内存混乱。
哈罗德

+1为基于令牌的解决方案!考虑到性能,了解基于令牌的解析是一件很愉快的事情……而且,一如既往的好人展示了如何通过token_get_all()解析常量。非常感谢你!
mwatzer

大概这仅作用于单个文件,并且不会从父类继承任何常量。实际上,该技术甚至不关心类-它将为您提供文件中的所有常量,即使是在全局范围内。这是一个很好的探索工具。
杰森


13

根据PHP文档的注释,如果您能够使用ReflectionClass(PHP 5):

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

来源在这里。


9

使用ReflectionClass并getConstants()给出您想要的:

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

输出:

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

6

静态方法特质-营救

看起来这是将Traits与静态函数结合使用来扩展类功能的好地方。特性也可以让我们在任何其他类中实现此功能,而无需一遍又一遍地重写相同的代码(保持DRY)。

在Profile类中使用我们的自定义'ConstantExport'特性。对需要此功能的每个类都这样做。

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

}

使用范例

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

print_r($constList); // TEST

输出:

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

5

是的,您需要使用反射。看一下输出

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

那应该让您对所要看的东西有个想法。


4

在类内部具有一个返回其自身常量的方法很方便。
您可以这样做:

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

3

为什么不将它们作为数组放在一个类变量中呢?使循环更容易。

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

2
因为数组不是常量?如果将某些本应是常量的东西实现为变量,则可能会无意间更改或设置它。换句话说,您不能依赖于它们保持不变。
GordonM 2011年

3

最终有了名称空间:

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

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_());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.