Отримайте значення динамічно вибраної константи класу в PHP


114

Я хотів би мати можливість зробити щось подібне:

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

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

Це не працює. Чи існує прямий спосіб зробити щось рівнозначне? Зауважте, що я застряг із класом; це в бібліотеці, яку я не можу переписати. Я пишу код, який бере аргументи в командному рядку, і мені дуже хотілося б, щоб він іменував символічні імена замість ідентифікаційних чисел.


Можна спробувати ThingIDs::{$thing}?
Девід Родрігес

Вже пробував. Отримує мені помилку розбору замість фатальної помилки виконання.
Бен

Відповіді:


182

$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));
Девід Баукум

4
@DavidBaucum, чому б ти хотів це надмірно ускладнити? Запит досить простий і не передбачає зовнішнього введення, керованого користувачем. Крім цього, ви викликаєте іншу функцію, тому що, я думаю, вам не подобається, що рядок поєднується з роздільниками?
ReSpawN

5
Залежно від вашого випадку використання, моє рішення є менш складним. Зокрема, якщо ви використовуєте автоматичне завантаження PSR-4, тоді ваш код може бути некрасивим, щоб FQDN прописано всюди. За допомогою використання useу верхній частині файлу, а потім використання ::classметоду магічного отримання FQDN покращує читабельність.
Девід Баукум

27

Використовуйте відбиття

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

3
Роздуми дійсно дають багато уявлення про класи, методи та інше, і, здається, багато людей бояться зробити цей крок, щоб зрозуміти їх. Чудова відповідь.
Майк Макінтош

2
@mikemackintosh Я вжив заходів, щоб їх зрозуміти, але не бачив у плані впливу на ефективність та прийняту відповідь. ТО - це те, що мені цікаво знати. Миттєвий пошук нового класу здається, що він матиме більшу ефективність, ніж просто статичний виклик константи. Які ваші думки з цього приводу?
dudewad

13

Якщо ви використовуєте простори імен, вам слід включити простір імен з класом.

echo constant('My\Application\ThingClass::ThingConstant'); 

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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.