2010-12-06 11 views
3

特定のクラスが特定のインタフェースを拡張または実装しているかどうかを確認するには、が必要です。PHP instanceof over文字列と初期化不可クラス

注:クラス名は可変ストリングです。

ユーザはクラスのリストからクラスを選択し、システムはそのクラスが特定のインタフェースを実装しているかどうかを確認することになっています。クラスのリストは(現在実行中のPHPソフトウェアに従って)可変であり、これらのクラスのいくつかは初期化され、他のクラスは初期化できません。

ここで私が使用しているコードです:

function is_instance_of($obj,$cls){ 
    if(is_string($obj))$obj=new $obj(); 
    if(PHP_MAJOR_VERSION>4)return $obj instanceof $cls; 
    if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls)); 
    return false; 
} 

var_dump(is_instance_of('MyClass','IMyInterface')); // in theory, true 
var_dump(is_instance_of('Closure','IMyInterface')); // FATAL ERROR 

最後のテストは、次のエラーアップを示しています。私が試した

​​

もの:

  • $obj=new @$obj();を使用する: - エラーが隠されていますが、それでもまだ失敗しています。
  • 問題のあるブロックの周りtry{}catch(){}を使用して: - :無条件

は必須クラスの初期化は、この方法で使用されることに注意してくださいfalseを返します。.. - 異なる何も'class' instanceof 'class'($のobjがある文字列)を使用して

  • は起こりません.sucks。インスタンスを作成すると、不要なメモリ消費、速度の低下、エラーの発生が増えます(パラメータを使用せずにインスタンス化すると、HDDが破壊されるという奇妙なクラスを想像してください)。 他の方法があれば、私はそれについて知りたいと思うだけです。


    編集:これは、最終的なコード(たぶん)である: -

    /** 
    * Cross-version instanceof replacement. 
    * @param object $obj The instance to check. 
    * @param stirng $cls The class/interface name to look for. 
    * @return boolean Whether an object extends or implements a particular class 
    *  or interface. 
    * @link http://stackoverflow.com/questions/4365567/php-instanceof-over-strings-and-non-initializable-classes 
    */ 
    function is_instance_of($obj,$cls){ 
        if(is_string($obj) || PHP_MAJOR_VERSION>4){ 
         $rc=new ReflectionClass($obj); 
         return $rc->implementsInterface($cls); 
        }else{ 
         if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls)); 
         return false; 
        } 
    } 
    
  • +1

    副行為として、この行はPHPバージョン<5では解析エラーを引き起こしませんか? 'if(PHP_MAJOR_VERSION> 4)は$ obj instanceof $ cls;を返します。条件付きではPHP 4以降では*実行*を防ぎますが、パーサーはそれを解析しなければなりません。それについて幸せ。 – cdhowie

    +0

    良い点。そのことはよくわからない。それを修正するための任意のアイデア?私はgood ol 'eval;を使うことができました;):D – Christian

    答えて

    2

    は、例えば、代わりにPHPのReflectionClassを使用してみてください

    $rc = new ReflectionClass($obj); 
    return $rc->implementsInterface($cls); 
    
    +0

    私は別の方法が好きですが、これは確かに良い選択です。 – Christian

    +0

    編集中。 ReflectionClassは、オブジェクトが与えられたときに正常に動作するように思われるので、さらに簡単です。 –

    +0

    実際には、ReflectionClassが利用できるPHPバージョンがわからないので、PHP <5の互換性を維持する必要がある場合、オプションではない可能性があります。 –

    0

    ReflectionClassを使用します。

    function is_instance_of($obj,$cls){ 
        $ref=new ReflectionClass($obj); 
        return in_array($cls, array_keys($ref->getInterfaces()); 
    } 
    
    +0

    ドキュメントには、コンストラクタに文字列を与える必要があることが示唆されています。与えられた例から、ときどきオブジェクトが与えられるかもしれないようである。 –

    +0

    ドキュメントは間違っているように見えますが、試してみるとインスタンスで正常に動作します。 –

    +0

    はい、それは少なくとも私のPHPバージョンのインスタンスと文字列で動作します – mck89