Ruft den Wert der dynamisch ausgewählten Klassenkonstante in PHP ab

114

Ich würde gerne so etwas machen können:

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

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

Das funktioniert nicht. Gibt es eine einfache Möglichkeit, etwas Äquivalentes zu tun? Beachten Sie, dass ich mit der Klasse festgefahren bin; Es befindet sich in einer Bibliothek, die ich nicht umschreiben kann. Ich schreibe Code, der Argumente in der Befehlszeile akzeptiert, und ich möchte wirklich , dass symbolische Namen anstelle von ID-Nummern verwendet werden.

Ben
quelle
Kannst du es versuchen ThingIDs::{$thing}?
David Rodrigues
Schon versucht. Erhält einen Analysefehler anstelle eines schwerwiegenden Laufzeitfehlers.
Ben

Antworten:

182

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

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

Dan Simon
quelle
1
Randnotiz: Wenn Sie zuerst überprüfen möchten, ob die Konstante definiert ist oder nicht, ist esdefined("ThingIDs::$thing");
Parris Varney
3
oder $ id = Konstante ("self :: $ thing");
Linie
3
Ähnlich wie$id = constant(sprintf('%s::%s', ThingIDs::class, $thing));
David Baucum
4
@ DavidBaucum, warum willst du das überkomplizieren? Die Anfrage ist recht einfach und beinhaltet keine externen, vom Benutzer manipulierbaren Eingaben. Abgesehen davon rufen Sie eine andere Funktion auf, weil Sie die Zeichenfolge nicht mit Trennzeichen verketten möchten.
ReSpawN
5
Abhängig von Ihrem Anwendungsfall ist meine Lösung weniger kompliziert. Insbesondere wenn Sie das automatische Laden von PSR-4 verwenden, kann es in Ihrem Code hässlich sein, den FQDN überall buchstabieren zu lassen. Durch die Verwendung useoben in der Datei und die anschließende Verwendung der ::classMethode zum magischen Abrufen des vollqualifizierten Domänennamens wird die Lesbarkeit verbessert.
David Baucum
27

Verwenden Sie Reflexion

$r = new ReflectionClass('ThingIDs');
$id = $r->getConstant($thing);
Phil
quelle
3
Reflexionen bieten wirklich viel Einblick in Klassen, Methoden und mehr, und es scheint, dass viele Menschen Angst haben, diesen Schritt zu tun, um sie zu verstehen. Gute Antwort.
Mike Mackintosh
2
@mikemackintosh Ich habe Schritte unternommen, um sie zu verstehen, aber nicht viel in Bezug auf die Auswirkungen auf die Leistung im Vergleich zur akzeptierten Antwort gesehen. Das interessiert mich. Das Instanziieren einer neuen Klasse scheint einen größeren Leistungseinbruch zu haben, als einfach eine Konstante statisch aufzurufen. Was denkst du darüber?
Dudewad
13

Wenn Sie Namespaces verwenden, sollten Sie den Namespace in die Klasse aufnehmen.

echo constant('My\Application\ThingClass::ThingConstant'); 
Jordi Kroon
quelle
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');
Josh
quelle
2

Hilfsfunktion

Sie können eine Funktion wie diese verwenden:

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

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

Es braucht zwei Argumente:

  • Klassenname oder Objektinstanz
  • Name der Klassenkonstante

Wenn eine Objektinstanz übergeben wird, wird ihr Klassenname abgeleitet. Wenn Sie PHP 7 verwenden, können Sie verwenden::class entsprechenden Klassennamen übergeben, ohne an Namespaces denken zu müssen.

Beispiele

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'
Glutexo
quelle
0

Wenn Sie einen Verweis auf die Klasse selbst haben, können Sie Folgendes tun:

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

Mein Problem war diesem Thema ähnlich. Wenn Sie das Objekt, aber nicht den Klassennamen haben, können Sie Folgendes verwenden:

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

$constant_value = constant($class_name.'::'.$class_const);
Andrei
quelle