2011-12-14 10 views
1

PHPで列挙を処理する方法を見つけようとしていました。 私が見つけたアプローチのどれも実際に列挙を使用して関数/メソッドへの引数を制限することはできません。これがenumを必要とする主な理由です。PHPリフレクションを使用して列挙を作成する

だから私は自分自身を作成し​​ようとして始めたが、今リフレクションを使用して問題に遭遇しています

<?php 

class Enum { 
    private $_value; 
    protected function __construct($value) { 
     $this->_value = $value; 
    } 

    public function getValue() { 
     return $this->_value; 
    } 

    protected static function enumerate($class) { 
     $ref = new ReflectionClass($class); 
     $instances = array(); 
     foreach ($ref->getStaticProperties() as $name => $value) { 
      $ref->setStaticPropertyValue($name, new $class($value)); 
     } 
    } 
} 

class Book extends Enum { 
    public static $COMIC = 1; 
    public static $NOVEL = 2; 
    public static $EDUCATIONAL = 3; 

    public static function enumerate() { 
     parent::enumerate(__CLASS__); 
    } 
} 
Book::enumerate(); 

function read(Book $book) { 
    echo '<hr/>'; 
    var_dump($book); 
} 

read(Book::$COMIC); 
read(Book::$EDUCATIONAL); 

?> 

私は2つのブックがそれぞれの値を持つオブジェクトを示すために出力を期待し、代わりに私はこれを得た:

object(Book)#2 (1) { ["_value:private"]=> object(Book)#2 (1) { ["_value:private"]=> *RECURSION* } } 
object(Book)#4 (1) { ["_value:private"]=> object(Book)#4 (1) { ["_value:private"]=> *RECURSION* } } 

setStaticPropertyValueに入る値(new $class)は正しいものであり、3つしか作成されていません。

getStaticPropertiesは、静的なプロパティ(必要に応じて)だけを受け取り、private $_valueが割り当てられている唯一の場所はコンストラクタです。 完全性のために、コンストラクタは3回だけ呼び出され、コンストラクタの内部では、値は期待どおり1,2または3になります。要するに、setStaticPropertyValueを呼び出すまではすべて正常です。

私はここで何が起こっているのか理解できません。 private $_valueはどこで、なぜこのように間違った価値が割り当てられていますか?反射を間違った方法で使っていますか?これら無限の再帰オブジェクトを作成するのは何ですか?

答えて

1

これは魅力的です。私は、PHPの境界を押し広げるものを横断して実行すると、それが大好きです。

これはちょっと極端なようだが、反射の速さによってはかなり遅いかもしれない。

私が書いたフレームワークでは、簡単なenum functionを作成しました。それは、定義を自動化することだけです。タイプ制限ができるので、あなたのアプローチがより好きです。

あなたのコードは私の仕事です。私は以下の編集を投稿しています - 主に変更を書式設定していますので、読みやすくなりました。

私が行ったことを確認してください。私はこれを5.3.5と5.2.17でテストしました。いずれかでうまく動作します。

<?php 
header('content-type: text/plain'); 

Book::enumerate(); 
Book::$COMIC->read(); 
read(Book::$EDUCATIONAL); 
read(Book::$NOVEL); 

class Enum 
{ 
    private $_value; 
    protected function __construct($value) 
    { 
     $this->_value = $value; 
    } 

    public function getValue() 
    { 
     return $this->_value; 
    } 

    protected static function enumerate($class) 
    { 
     $ref = new ReflectionClass($class); 
     $instances = array(); 

     foreach ($ref->getStaticProperties() as $name => $value) 
     { 
      $ref->setStaticPropertyValue($name, new $class($value)); 
     } 
    } 
} 

class Book extends Enum 
{ 
    public static $COMIC = 'comic'; 
    public static $NOVEL = 'novel'; 
    public static $EDUCATIONAL = 'edu'; 

    public static function enumerate() 
    { 
     parent::enumerate(__CLASS__); 
    } 
    public function read() 
    { 
     echo "\nReading a {$this->getValue()} book\n"; 
    } 
} 

function read(Book $book) 
{ 
    echo "\nReading a {$book->getValue()} book\n"; 
} 

出力

Reading a comic book 

Reading a edu book 

Reading a novel book 
+0

のvar_dumpを使用して、元のコードを実行して、私は** **再帰メッセージを受信しませんでした。 –

+0

あなたのバージョンは私にとってはうまくいきません。私はPHP 5.2.4を使用していますので、使用しているものの後ろにいくつかの修正があります。 私は、いくつかの問題がinbetweenの間に修正されている必要があると仮定しています。残念ながら、私は私たちのプロダクションバージョンではPHPを更新することはできませんが、少なくとも最近のバージョンでは動作します。 – MartijnCMT

+0

パフォーマンスに関しては、反射のものは1回限りのコストなので、それほど悪くはありません。 – MartijnCMT

関連する問題