ฉันสามารถกำหนดค่าของ CONST ในคลาส PHP ได้หรือไม่?


140

ฉันมีข้อ จำกัด หลายอย่างของ CONST ในบางคลาสและต้องการรับรายชื่อพวกเขา ตัวอย่างเช่น:

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

มีวิธีใดบ้างที่จะได้รายการของ CONST ที่นิยามไว้ในProfileคลาส? เท่าที่ฉันสามารถบอกได้ตัวเลือกที่ใกล้เคียงที่สุด ( 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')

คุณสามารถทำได้โดยใช้การสะท้อน ค้นหา "พิมพ์ค่าคงที่คลาส" ในหน้านั้นเพื่อดูตัวอย่าง
n3rd

ใช้ Reflection และ ReflectionClass บน Cl คุณสามารถใช้ฟังก์ชัน getConstants nz.php.net/manual/en/class.reflectionclass.php
Tim Ebenezer

สะท้อนจะเป็นผู้ช่วยให้รอดของคุณ
Björn

คำตอบ:


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
NBs เล็กน้อยสองรายการ: อันดับแรกใน 5.3 Profileสามารถใช้เป็นอาร์กิวเมนต์สำหรับตัวสร้างตัวสะท้อนได้โดยไม่ต้องใส่เครื่องหมายอัญประกาศ (ชื่อคลาสอย่างง่าย) สองเพื่อให้ชัดเจนสมบูรณ์คีย์ของอาร์เรย์ผลลัพธ์เป็นสตริงไม่ใช่ค่าคงที่เนื่องจากอาจมีการจัดรูปแบบที่นี่เพื่อแนะนำ (มูลค่าการกล่าวขวัญเฉพาะเมื่อ fn นั้นไม่มีเอกสาร )
Benji XVI

11
@Benji XVI ใน 5.3 หากคุณเปิดการแจ้งเตือนคุณจะไม่สามารถใช้งานได้Profileหากไม่มีเครื่องหมายอัญประกาศเนื่องจากจะแสดงข้อผิดพลาดต่อไปนี้: ข้อสังเกต: การใช้โปรไฟล์คงที่ที่ไม่ได้กำหนด - สันนิษฐานว่าเป็น 'โปรไฟล์' ดังนั้นฉันขอแนะนำให้รักษาคำพูดไว้'Profile'
toneplex

10
มันเป็นการดีที่จะกำหนดตรรกะที่เกี่ยวข้องกับค่าคงที่ภายในคลาสดังนั้นคุณไม่จำเป็นต้องสร้างอากิวเมนต์ตัวสร้างฮาร์ดโค้ด แต่ใช้__CLASS__แทน
ลุค Adamczewski

7
new ReflectionClass(Profile::class)ทำงานได้ดีเช่นกัน
mtizziani

@tizziani จริง แต่ระวังของเนมสเปซ! สมมติว่าคุณมีเนมสเปซ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เป็น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 ตามที่ผู้โพสต์คนอื่น ๆ กล่าวถึงมันเป็นสิ่งสำคัญที่จะต้องเข้าใจการทำงานของ "under-the-hood" และสามารถทำได้โดยไม่ต้องทำซ้ำ แสดงที่ดี
Dereleased

1
หากคุณไม่ต้องการให้โหลดคลาสลงในหน่วยความจำ token_get_all เป็นทางเลือกที่ยอดเยี่ยม มันเร็วกว่า Reflection มากและไม่เกะกะความจำกระบวนการถ้าคุณต้องการทำสิ่งนี้กับคลาสจำนวนมาก
แฮโรลด์

+1 สำหรับโซลูชันที่ใช้โทเค็น! การทำความเข้าใจกับการแยกวิเคราะห์โทเค็นเป็นเรื่องที่น่ายินดีเมื่อพิจารณาถึงประสิทธิภาพ ... และเช่นเคยมีคนดีคนหนึ่งที่แสดงวิธีแยกค่าคงที่ผ่าน token_get_all () ขอบคุณมาก!
mwatzer

สันนิษฐานว่าสิ่งนี้ทำหน้าที่ในไฟล์เดียวเท่านั้นและไม่สืบทอดค่าคงที่ใด ๆ จากคลาสพาเรนต์ ในความเป็นจริงเทคนิคนี้ไม่สนใจแม้แต่คลาส - มันจะให้ค่าคงที่ทั้งหมดในไฟล์แม้แต่ในขอบเขตทั่วโลก มันเป็นเครื่องมือที่ยอดเยี่ยมในการสำรวจ
เจสัน




6

ลักษณะที่มีวิธีการคงที่ - เพื่อช่วยเหลือ

ดูเหมือนว่าเป็นสถานที่ที่ดีในการใช้คุณลักษณะกับฟังก์ชั่นคงที่เพื่อขยายฟังก์ชั่นการเรียน ลักษณะจะช่วยให้เราสามารถใช้ฟังก์ชั่นนี้ในชั้นเรียนอื่น ๆ โดยไม่ต้องเขียนรหัสเดิมซ้ำแล้วซ้ำอีก (อยู่ต่อไป)

ใช้คุณลักษณะ '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
)


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:

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.