使用PHP反射来构建枚举

时间:2011-12-14 10:21:00

标签: php reflection static enums

我试图在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);

?>

我希望输出显示两个具有各自值的Book对象,而不是我得到的:

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

进入new $class的值(setStaticPropertyValue)是正确的,并且只创建了其中的三个。

getStaticProperties仅获取静态属性(应该如此),private $_value分配的唯一位置在构造函数中。 为了完整起见,构造函数只被调用三次并且在构造函数中,正如预期的那样,值只有1,2或3.简而言之,在调用setStaticPropertyValue之前,一切似乎都很好。

我无法弄清楚这里发生了什么。 private $_value在哪里以及为什么分配了这个错误的值?我用反射方式错了吗?什么是创建这些无限递归对象?

1 个答案:

答案 0 :(得分: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