PHP'de dinamik olarak seçilen sınıf sabitinin değerini alın


114

Bunun gibi bir şey yapabilmek isterim:

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

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

Bu çalışmıyor. Eşdeğer bir şey yapmanın basit bir yolu var mı? Sınıfa bağlı kaldığımı unutmayın; yeniden yazamayacağım bir kitaplıkta. Komut satırında argümanlar alan kod yazıyorum ve gerçekten kimlik numaraları yerine sembolik isimler almasını istiyorum.


Deneyebilir ThingIDs::{$thing}misin
David Rodrigues

Zaten denedim. Ölümcül bir çalışma zamanı hatası yerine bana bir ayrıştırma hatası veriyor.
Ben

Yanıtlar:


183

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

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


1
Yan not: önce sabitin tanımlanıp tanımlanmadığını kontrol etmek istiyorsanız, budefined("ThingIDs::$thing");
Parris Varney

3
veya $ id = sabit ("self :: $ şey");
Satır

3
Buna benzer,$id = constant(sprintf('%s::%s', ThingIDs::class, $thing));
David Baucum

4
@DavidBaucum neden bunu aşırı karmaşık hale getirmek istiyorsun? İstek oldukça basittir ve dışarıdan, kullanıcı tarafından manipüle edilebilir girdi içermez. Bunun dışında, başka bir işlevi çağırıyorsunuz çünkü, sanırım dizenin sınırlayıcılarla birleştirilmesini sevmiyorsunuz?
ReSpawN

5
Kullanım durumunuza bağlı olarak, çözümüm daha az karmaşıktır. Özellikle PSR-4 otomatik yüklemesini kullanıyorsanız, FQDN'nin her yerde yazılması kodunuzda çirkin olabilir. useDosyanın üst kısmında kullanım ve ardından ::classFQDN'yi sihirli bir şekilde elde etmek için yöntemi kullanmak okunabilirliği artırır.
David Baucum

27

Yansımayı Kullan

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

3
Düşünceler gerçekten sınıflar, yöntemler ve daha fazlası hakkında pek çok fikir veriyor ve birçok insan onları anlamak için bu adımı atmaktan korkuyor gibi görünüyor. Mükemmel cevap.
Mike Mackintosh

2
@mikemackintosh Bunları anlamak için adımlar attım, ancak kabul edilen cevaba kıyasla performans etkisi açısından pek bir şey görmedim. BU, bilmekle ilgilendiğim bir şey. Yeni bir sınıfın somutlaştırılması, bir sabiti statik olarak çağırmaktan daha büyük bir performans vuruşuna sahip gibi görünüyor. Bununla ilgili düşüncelerin neler?
dudewad

13

Ad alanları kullanıyorsanız, ad alanını sınıfla birlikte eklemelisiniz.

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

Yardımcı işlevi

Bunun gibi bir işlevi kullanabilirsiniz:

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

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

İki argüman alır:

  • Sınıf adı veya nesne örneği
  • Sınıf sabiti adı

Bir nesne örneği aktarılırsa, sınıf adı çıkarılır. PHP 7 kullanıyorsanız, ::classad alanlarını düşünmek zorunda kalmadan uygun sınıf adını geçirmek için kullanabilirsiniz .

Örnekler

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

Sınıfın kendisine bir referansınız varsa, şunları yapabilirsiniz:

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

0

Benim sorunum bu konuyla benzerdi. Nesneye sahip olduğunuzda ancak sınıf adına sahip olmadığınızda, şunları kullanabilirsiniz:

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

$constant_value = constant($class_name.'::'.$class_const);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.