CONST를 PHP 클래스에서 정의 할 수 있습니까?


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')

reflection을 사용하여이 작업을 수행 할 수 있습니다 . 해당 페이지에서 "인쇄 클래스 상수"를 검색하여 예제를보십시오.
— n3rd

Cl에서 Reflection과 ReflectionClass를 사용하면 getConstants nz.php.net/manual/en/class.reflectionclass.php
— Tim Ebenezer

답변:


245

이것을 위해 Reflection 을 사용할 수 있습니다 . 이 작업을 많이 수행하면 결과 캐싱을보고 싶을 수 있습니다.

<?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입니다 전용으로 언급 문서화 .)
— 벤지 XVI

11
@Benji XVI 5.3에서 알림을 설정 한 경우 Profile다음 오류가 표시되므로 따옴표없이 사용할 수 없습니다 . 알림 : 정의되지 않은 상수 프로필 사용- '프로파일'이라고 가정합니다. 그래서 따옴표를 유지하는 것이 좋습니다'Profile'
— toneplex

10
클래스 내부에 상수 관련 논리를 정의하는 것이 좋으므로 생성자 인수를 하드 코딩 할 필요가 없지만 __CLASS__대신 사용하십시오.
— Luke Adamczewski

7
new ReflectionClass(Profile::class)잘 작동
— mtizziani

@mtizziani true이지만 네임 스페이스를 알고 있어야합니다! 하자 당신이 네임 스페이스가 있다고 City클래스와 B이 - B::class잘 작동,하지만 당신은 예를 들어, 이름 공간에서 그 사용하려는 경우 Jungle- 전화 B::class로를 포함하지 않고 거기를 use초래할 것 Jungle\B(! 정글 전혀 B를 가지고 있지 않더라도)
— jave.web

22

이

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

1
+1 이것은 클래스 상수를 얻기위한 내장 된 절차 적 PHP 함수를 찾을 수 없기 때문에 가능합니다.
— BoltClock

1
아마도 거의 필요하지 않기 때문일 것입니다. 영업 이익은 설정하여 메타 구성 작업을 수행 할 수 있습니다 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, 다른 포스터에서 언급 한 것처럼 리플렉션을 사용하기에 가장 좋은시기라고 말하지만, "사후"의 작업을 이해하고 필요하지 않은 경우 작업없이 복제하거나 복제 할 수 있어야합니다. 좋은 공연.
— 2009

1
클래스를 메모리에로드하지 않으려면 token_get_all이 환상적인 대안입니다. 리플렉션보다 훨씬 빠르며 많은 클래스 에서이 작업을 수행 해야하는 경우 프로세스 메모리를 어지럽히 지 않습니다.
— Harold

토큰 기반 솔루션 +1! 토큰 기반 구문 분석을 이해하는 것은 성능을 고려하는 즐거움입니다 ... 항상 그렇듯이 token_get_all ()을 통해 상수를 구문 분석하는 방법을 보여주는 훌륭한 사람이 있습니다. 대단히 감사합니다!
— mwatzer

아마도 이것은 단일 파일에서만 작동하며 부모 클래스에서 상수를 상속하지 않습니다. 실제로이 기법은 클래스에 신경 쓰지 않아도됩니다. 심지어 전역 범위에서도 파일의 모든 상수를 제공합니다. 그래도 탐색하기에 좋은 도구입니다.
— Jason


13

ReflectionClass (PHP 5)를 사용할 수 있다면 PHP 문서 주석에 따라 :

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'특성을 사용하십시오. 이 기능이 필요한 모든 수업에 적용하십시오.

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