PHPで動的に選択されたクラス定数の値を取得する


114

私はこのようなことができるようになりたいです:

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

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

これは機能しません。同等のことを行う簡単な方法はありますか?クラスにこだわっていることに注意してください。それは私が書き換えることができないライブラリにあります。私はコマンドラインで引数を取るコードを書いていて、ID番号ではなくシンボリック名を使ってもらいたいと思っています。


やってみThingIDs::{$thing}ませんか?
David Rodrigues、

すでに試しました。致命的なランタイムエラーの代わりに解析エラーを取得します。
ベン

回答:


182

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

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


1
補足:定数が定義されているかどうかを最初に確認したい場合は、次のようになりますdefined("ThingIDs::$thing");
Parris Varney

3
または$ id = constant( "self :: $ thing");
ライン

3
これと同様に、$id = constant(sprintf('%s::%s', ThingIDs::class, $thing));
デヴィッドBaucum

4
@DavidBaucumなぜこれを過度に複雑にしたいですか?リクエストは非常に単純で、外部のユーザー操作可能な入力は含まれません。それとは別に、別の関数を呼び出しているのは、おそらく、文字列を区切り文字で連結したくないからでしょうか。
ReSpawN 2016年

5
ユースケースにもよりますが、私のソリューションはそれほど複雑ではありません。特に、PSR-4オートローディングを使用している場合、コードのどこでもFQDNがスペルアウトされていると見づらくなることがあります。使用することでuseファイルの先頭に、次に使用する::class魔法のFQDNは、読みやすさを向上させ得るための方法を。
David Baucum、2016年

27

リフレクションを使用する

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

3
リフレクションは、クラスやメソッドなどについて多くの洞察を提供し、多くの人々がそれらを理解するためにその一歩を踏み出すことを恐れているようです。すばらしい答えです。
Mike Mackintosh

2
@mikemackintosh私はそれらを理解するための対策を講じましたが、パフォーマンスへの影響と受け入れられた答えの点であまり見ていません。それは私が知りたいものです。新しいクラスのインスタンス化は、単に静的に定数を呼び出すよりも大きなパフォーマンスヒットをもたらすようです。そのことについてどう思いますか?
dudewad 2013

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);
}

2つの引数を取ります。

  • クラス名またはオブジェクトインスタンス
  • クラス定数名

オブジェクトインスタンスが渡されると、そのクラス名が推測されます。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.