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のリストを取得する方法はありますか?私の知る限り、最も近いオプション(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')

リフレクションを使用してこれを行うことができます。そのページで「Print class constants」を検索して例を確認してください。
2009年

ClでReflectionおよびReflectionClassを使用すると、関数getConstants nz.php.net/manual/en/class.reflectionclass.php
Tim Ebenezer

回答:


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
2つのマイナーNB:最初に、5.3では、Profile引用符なしでリフレクターコンストラクターの引数として使用できます(単純なクラス名)。次に、完全に明確にするために、結果の配列のキーは文字列であり、定数ではなく、ここでのフォーマットが示唆しているようです。(fnは文書化されていないため、言及するだけの価値があります。)
Benji XVI

11
@Benji XVI 5.3では、通知がオンになっている場合Profile、次のエラーが表示されるため、引用符なしでは使用できません。通知:未定義の定数プロファイルの使用-「プロファイル」と見なされます。だから私は引用符を維持することをお勧めします'Profile'
トーンプレックス'28年

10
クラス内で定数に関連するロジックを定義するのは良いので、コンストラクター引数をハードコーディングする必要は__CLASS__なく、代わりに使用します。
Luke Adamczewski、2013年

7
new ReflectionClass(Profile::class)
正常に

@mtizziani trueですが、名前空間に注意してください!Cityクラスで名前空間があるとし ましょうB- B::classうまくいきますが、たとえば名前空間でそれらを使用すると、それを含めずにJungle呼び出すと、(JungleにBがまったくない場合でも)B::classuseJungle\B
jave.web

22

この

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

1
+1クラス定数を取得するための組み込みの手続き型PHP関数が見つからないため、これは少し残念です。
BoltClock

1
おそらくそれの必要性がほとんどないからでしょう。OPはtypesとして設定することでメタ設定を実行するall constants this class has場合があります。これは、ほとんどの場合、そして私の認められた限られた意見では、継承または型を持つ静的配列変数のいずれかで処理するほうが適切です(他の意味を持つ定数のための余地を残します/使用する)。
Wrikken

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を使用する絶好の機会だと思いますが、「内部」の仕組みを理解し、それらなしで実行できること、または必要に応じてそれらを複製できることも重要です。良いショー。
2009

1
クラスをメモリにロードしたくない場合、token_get_allは素晴らしい代替手段です。これは、Reflectionよりもはるかに高速であり、多くのクラスでこれを行う必要がある場合でも、プロセスメモリが乱雑になることはありません。
ハロルド

トークンベースのソリューションの+1!トークンベースの解析を理解することは、パフォーマンスを考えると喜びです...そして、いつものように、token_get_all()を介して定数を解析する方法を自慢する素晴らしい人がいます。どうもありがとうございました!
mwatzer 2016

おそらくこれは単一のファイルのみに作用し、親クラスから定数を継承しません。実際、この手法はクラスについてさえ気にしません。グローバルスコープでも、ファイル内のすべての定数を提供します。それは探検するための素晴らしいツールです。
Jason、


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

静的メソッドの特性-救いの手に

静的関数でトレイトを使用してクラスの機能を拡張するのに最適な場所のようです。トレイトを使用すると、同じコードを何度も書き直さなくても(DRYのまま)、この機能を他のクラスに実装できます。

カスタムの 'ConstantExport'トレイトをProfileクラスで使用します。この機能が必要なすべてのクラスに対してそれを行います。

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

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_());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.