รับค่าของค่าคงที่คลาสที่เลือกแบบไดนามิกใน PHP


114

ฉันต้องการที่จะทำสิ่งนี้:

class ThingIDs
{
    const Something = 1;
    const AnotherThing = 2;
}

$thing = 'Something';
$id = ThingIDs::$thing;

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


คุณสามารถลองThingIDs::{$thing}?
David Rodrigues

พยายามแล้ว. ให้ข้อผิดพลาดในการแยกวิเคราะห์แทนข้อผิดพลาดรันไทม์ร้ายแรง
เบ็น

คำตอบ:


183

$id = constant("ThingIDs::$thing");

http://php.net/manual/en/function.constant.php


1
หมายเหตุด้านข้าง: หากคุณต้องการตรวจสอบก่อนว่ามีการกำหนดค่าคงที่หรือไม่นั่นคือdefined("ThingIDs::$thing");
Parris Varney

3
หรือ $ id = คงที่ ("self :: $ thing");
สาย

3
คล้ายกับสิ่งนี้$id = constant(sprintf('%s::%s', ThingIDs::class, $thing));
David Baucum

4
@DavidBaucum ทำไมคุณถึงต้องการซับซ้อนมากเกินไปนี้? คำขอค่อนข้างง่ายและไม่เกี่ยวข้องกับอินพุตภายนอกที่ผู้ใช้จัดการได้ นอกเหนือจากนั้นคุณกำลังเรียกใช้ฟังก์ชันอื่นเพราะฉันเดาว่าคุณไม่ชอบให้สตริงเชื่อมต่อกับตัวคั่น?
ReSpawN

5
วิธีแก้ปัญหาของฉันซับซ้อนน้อยลงทั้งนี้ขึ้นอยู่กับการใช้งานของคุณ โดยเฉพาะอย่างยิ่งหากคุณใช้การโหลดอัตโนมัติ PSR-4 การที่รหัสของคุณจะมี FQDN สะกดทุกที่นั้นอาจเป็นเรื่องน่าเกลียด โดยใช้useที่ด้านบนของไฟล์จากนั้นใช้::classวิธีการเพื่อรับ FQDN อย่างน่าอัศจรรย์ช่วยเพิ่มความสามารถในการอ่าน
David Baucum

27

ใช้ Reflection

$r = new ReflectionClass('ThingIDs');
$id = $r->getConstant($thing);

3
การไตร่ตรองให้ข้อมูลเชิงลึกมากมายเกี่ยวกับชั้นเรียนวิธีการและอื่น ๆ และดูเหมือนว่าหลายคนกลัวที่จะทำตามขั้นตอนนั้นเพื่อทำความเข้าใจกับพวกเขา คำตอบที่ดี
Mike Mackintosh

2
@mikemackintosh ฉันได้ทำตามขั้นตอนเพื่อทำความเข้าใจแล้ว แต่ยังไม่เห็นผลกระทบด้านประสิทธิภาพเทียบกับคำตอบที่ยอมรับมากนัก นั่นคือสิ่งที่ฉันสนใจอยากรู้ การสร้างอินสแตนซ์คลาสใหม่ดูเหมือนว่าจะมีประสิทธิภาพที่ยอดเยี่ยมกว่าการเรียกค่าคงที่แบบคงที่ คุณคิดอย่างไรกับเรื่องนั้น?
dudewad


3
<?php

class Dude {
    const TEST = 'howdy';
}

function symbol_to_value($symbol, $class){
    $refl = new ReflectionClass($class);
    $enum = $refl->getConstants();
    return isset($enum[$symbol])?$enum[$symbol]:false;
}

// print 'howdy'
echo symbol_to_value('TEST', 'Dude');

3

ฟังก์ชันตัวช่วย

คุณสามารถใช้ฟังก์ชันเช่นนี้:

function class_constant($class, $constant)
{
    if ( ! is_string($class)) {
        $class = get_class($class);
    }

    return constant($class . '::' . $constant);
}

ต้องใช้สองอาร์กิวเมนต์:

  • ชื่อคลาสหรืออินสแตนซ์วัตถุ
  • ชื่อคงที่ของคลาส

หากส่งผ่านอินสแตนซ์อ็อบเจ็กต์ชื่อคลาสจะถูกอนุมาน หากคุณใช้ PHP 7 คุณสามารถใช้::classเพื่อส่งผ่านชื่อคลาสที่เหมาะสมโดยไม่ต้องคิดถึงเนมสเปซ

ตัวอย่าง

class MyClass
{
    const MY_CONSTANT = 'value';
}

class_constant('MyClass', 'MY_CONSTANT'); # 'value'
class_constant(MyClass::class, 'MY_CONSTANT'); # 'value' (PHP 7 only)

$myInstance = new MyClass;
class_constant($myInstance, 'MY_CONSTANT'); # 'value'

0

หากคุณมีการอ้างอิงถึงคลาสตัวเองคุณสามารถทำสิ่งต่อไปนี้:

if (defined(get_class($course). '::COURSES_PER_INSTANCE')) {
   // class constant is defined
}

0

ปัญหาของฉันคล้ายกับเรื่องนี้ เมื่อคุณมีวัตถุ แต่ไม่มีชื่อคลาสคุณสามารถใช้:

$class_name = get_class($class_object);
$class_const = 'My_Constant';

$constant_value = constant($class_name.'::'.$class_const);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.