Tôi có thể định nghĩa CONST trên một lớp PHP không?


140

Tôi có một số CONST được định nghĩa trên một số lớp và muốn có một danh sách về chúng. Ví dụ:

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

Có cách nào để có được danh sách các CONST được định nghĩa trên Profilelớp không? Theo như tôi có thể nói, tùy chọn gần nhất ( get_defined_constants()) sẽ không thực hiện được.

Những gì tôi thực sự cần là một danh sách các tên liên tục - đại loại như thế này:

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

Hoặc là:

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

Hoặc thậm chí:

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

Bạn có thể làm điều này bằng cách sử dụng sự phản chiếu . Tìm kiếm "Hằng số lớp in" trên trang đó để xem ví dụ.
thứ ba

Sử dụng Reflection và ReflectionClass trên Cl, bạn có thể sử dụng hàm getConstants nz.php.net/manual/en/ class.reflection class.php
Tim Ebenezer

Câu trả lời:


245

Bạn có thể sử dụng Reflection cho việc này. Lưu ý rằng nếu bạn đang làm điều này rất nhiều, bạn có thể muốn xem bộ đệm kết quả.

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

Đầu ra:

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

4
Hai NB nhỏ: đầu tiên, trong 5.3, Profilecó thể được sử dụng làm đối số cho hàm tạo phản xạ, không có dấu ngoặc kép (tên lớp đơn giản); thứ hai, để hoàn toàn rõ ràng, các khóa của mảng kết quả là các chuỗi, không phải là hằng số vì định dạng ở đây có thể được đưa ra để đề xuất. (Chỉ đáng nói khi fn không có giấy tờ .)
Benji XVI

11
@Benji XVI Trong 5.3 nếu bạn bật thông báo, bạn sẽ không thể sử dụng Profilemà không có dấu ngoặc kép, vì nó sẽ hiển thị lỗi sau: Lưu ý: Sử dụng Hồ sơ không xác định - giả định 'Hồ sơ'. Vì vậy, tôi khuyên bạn nên giữ dấu ngoặc kép'Profile'
toneplex

10
Thật tốt khi định nghĩa các hằng số liên quan logic bên trong lớp, vì vậy bạn không cần phải lập luận đối số của hàm tạo mã cứng mà sử dụng __CLASS__thay thế.
Luke Adamczewski

7
new ReflectionClass(Profile::class)cũng hoạt động tốt
mtizziani

@mtizziani đúng, nhưng hãy chú ý đến không gian tên! Giả sử bạn có không gian tên Cityvới lớp B- B::classsẽ hoạt động tốt, nhưng nếu bạn sử dụng những không gian đó trong ví dụ như không gian tên Jungle- gọi B::classở đó mà không bao gồm nó usesẽ dẫn đến Jungle\B(mặc dù Jungle hoàn toàn không có B!)
jave.web

22

Điều này

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

1
+1 Đây sẽ là vì tôi không thể tìm thấy bất kỳ hàm PHP thủ tục tích hợp nào để nhận các hằng số lớp, điều này hơi xấu hổ.
BoltClock

1
Có lẽ bởi vì có rất ít nhu cầu cho nó. OP có thể muốn thực hiện cấu hình meta bằng cách đặt typesnhư all constants this class has, trong hầu hết các trường hợp, và theo ý kiến ​​hạn chế được cấp của tôi, có thể được phục vụ tốt hơn với cả thừa kế hoặc biến mảng tĩnh với các loại (chừa chỗ cho các hằng số có ý nghĩa khác / sử dụng).
Wrikken

16

Sử dụng token_get_all () . Cụ thể là:

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

Đầu ra:

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

1
+1, mặc dù tôi sẽ nói rằng đây là thời điểm tuyệt vời để sử dụng Reflection như được đề cập bởi các áp phích khác, điều quan trọng là phải hiểu các hoạt động "dưới vỏ bọc" và có thể làm mà không cần chúng hoặc sao chép chúng nếu cần thiết. Chương trinh hay.
Vô chủ

1
Nếu bạn không muốn lớp của mình được tải vào bộ nhớ, token_get_all là một sự thay thế tuyệt vời. Nó NHIỀU nhanh hơn Reflection và không làm lộn xộn bộ nhớ tiến trình nếu bạn cần làm điều này với nhiều lớp.
Harold

+1 cho giải pháp dựa trên mã thông báo! Hiểu phân tích cú pháp dựa trên mã thông báo là một niềm vui khi xem xét hiệu suất ... và như mọi khi, có một người tuyệt vời thể hiện cách phân tích các hằng số thông qua token_get_all (). Cảm ơn rât nhiều!
mwatzer

Có lẽ điều này chỉ hoạt động trên một tệp duy nhất và không kế thừa bất kỳ hằng số nào từ các lớp cha. Trong thực tế, kỹ thuật này thậm chí không quan tâm đến lớp - nó sẽ cung cấp cho bạn tất cả các hằng số trong tệp, ngay cả trong phạm vi toàn cầu. Đó là một công cụ tuyệt vời để khám phá mặc dù.
Jason


13

Theo các nhận xét về tài liệu PHP, nếu bạn có thể sử dụng ReflectionClass (PHP 5):

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

Nguồn ở đây.


9

Sử dụng ReflectionClass và getConstants()đưa ra chính xác những gì bạn muốn:

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

Đầu ra:

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

6

Đặc điểm với phương pháp tĩnh - để giải cứu

Có vẻ như đây là một nơi tuyệt vời để sử dụng Đặc điểm với chức năng tĩnh để mở rộng chức năng lớp. Các đặc điểm cũng sẽ cho phép chúng tôi thực hiện chức năng này trong bất kỳ lớp nào khác mà không cần viết lại cùng một mã nhiều lần (giữ nguyên DRY).

Sử dụng Đặc điểm 'ConstantExport' tùy chỉnh của chúng tôi trong lớp Hồ sơ. Làm điều đó cho mọi lớp mà bạn cần chức năng này.

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

}

VÍ DỤ SỬ DỤNG

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

print_r($constList); // TEST

NGOÀI RA:

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

5

Vâng, bạn sử dụng sự phản chiếu . Nhìn vào đầu ra của

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

Điều đó sẽ cho bạn ý tưởng về những gì bạn sẽ xem xét.


4

Thật tiện lợi khi có một phương thức bên trong lớp để trả về các hằng số của chính nó.
Bạn có thể làm theo cách này:

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

Tại sao không đặt chúng trong một biến lớp như một mảng để bắt đầu? Làm cho nó dễ dàng hơn để lặp thông qua.

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

2
Bởi vì mảng không phải là hằng số? Nếu bạn thực hiện một cái gì đó được coi là một hằng số như một biến thì bạn có nguy cơ nó vô tình bị thay đổi hoặc không được đặt. Nói cách khác, bạn không thể phụ thuộc vào chúng không đổi.
GordonM

3

Cuối cùng với không gian tên:

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_());
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.