dop2144 2011-12-14 10:21
浏览 31
已采纳

使用PHP反射来构建枚举

I was trying to find a method to handle enumeration in PHP. None of the approaches I found can actually use enumeration to limit the arguments to functions/methods, which is the main reason I want enums.

So I started trying to create my own, but have now run into a problem using reflection:

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

?>

I expected output to show two Book objects with their respective values, instead I got this:

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* } }

The value (new $class) going into setStaticPropertyValue is correct and there are created only three of these.

getStaticProperties only picks up the static properties (as it should) and the only place the private $_value is assigned is in the constructor. For completeness sake, the constructor is called only three times and inside the constructor, the value is, as expected, only ever 1, 2 or 3. In short, everything seems to be perfectly fine until the calls to setStaticPropertyValue.

I can't figure out what is going on here. Where and why is the private $_value assigned this wrong value? Am I using reflection the wrong way? What is creating these infinite recursive objects?

  • 写回答

1条回答 默认 最新

  • dsbifvcxr458755493 2011-12-14 19:35
    关注

    This is fascinating. I love it when I run across things that push the boundaries of PHP.

    I have to say, though, that this seems a bit extreme, and depending on how fast reflection is, it might be fairly slow.

    For a framework I wrote, I created a simple enum function. All it's doing is automating defines. I like your approach better because you can type-restrict.

    Your code works for me. I'm posting my edits below - they are mainly formatting changes so I could read it more easily.

    Check out what I've done to it. I tested this with 5.3.5 and 5.2.17 - works fine on either one.

    <?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 "
    Reading a {$this->getValue()} book
    ";
        }
    }
    
    function read( Book $book )
    {
        echo "
    Reading a {$book->getValue()} book
    ";
    }
    

    Output

    Reading a comic book
    
    Reading a edu book
    
    Reading a novel book
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?