PHP反射-这是错误还是预期行为?

时间:2020-08-09 15:09:11

标签: php reflection

我正在创建一个使用ReflectionProperty的类,并且得到了奇怪的结果。

本质上,调用.basket-summary { min-height: 15rem; min-width: 10rem; padding-bottom: 1rem; margin-top: 10rem; } 返回的是一些完全不相关的数组的值。它是在看似随机的条件下完成的。

见下文:

$reflectionProperty->getType()->getName()

结果:

// this will be used as a type hinted property.
class DummyClass {
    public function __construct($arr) {}
}


// a class that sets its property values reflectively
class BaseClass {
    /** @var ReflectionProperty[] */
    private static $publicProps = [];

    /**
     * Gets public ReflectionProperties of the concrete class, and caches them
     * so we do not need to perform reflection again for this concrete class.
     *
     * @return ReflectionProperty[]
     * @throws ReflectionException
     */
    private function getPublicProps(){
        if (!static::$publicProps) {
            $concreteClass = get_class($this);
            static::$publicProps = (new ReflectionClass($concreteClass))
                ->getProperties(ReflectionProperty::IS_PUBLIC);
        }
        return static::$publicProps;
    }

    /**
     * For each public property in this class set value to the corresponding value from $propArr.
     *
     * @param $propArr
     * @throws ReflectionException
     */
    public function __construct($propArr) {
        $concreteClass = get_class($this);
        echo "Creating new instance of $concreteClass<br>";
        foreach ($this->getPublicProps() as $prop) {
            // get which property to set, its class, and value to pass to constructor
            $propName = $prop->getName();
            $propClass = $prop->getType()->getName();
            $propValue = $propArr[$propName];
            $propValueStr = var_export($propValue, true);
            // print out what we are about to do, and assert $propClass is correct.
            echo "---Setting: ->$propName = new $propClass($propValueStr)<br>";
            assert($propClass === "DummyClass", "$propClass !== DummyClass");
            // create the instance and assign it
            $refClass = new ReflectionClass($propClass);
            $this->$propName = $refClass->newInstanceArgs([$propValue]);
        }
    }
}

// a concrete implementation of the above class, with only 1 type hinted property.
class ConcreteClass extends BaseClass {
    public DummyClass $prop1;
}

// should create an instance of ConcreteClass
// with ->prop1 = new DummyClass(["foo"=>"abc123"])
$testArr1 = [
    "prop1" => ["foo" => "abc123"]
];
// should create an instance of ConcreteClass
// with ->prop1 = new DummyClass(["boo"=>"abc123def456"])
$testArr2 = [
    "prop1" => ["boo" => "abc123def456"]
];
$tc1 = new ConcreteClass($testArr1);
echo "Created TestClass1...<br><br>";
$tc2 = new ConcreteClass($testArr2);
echo "Created TestClass2...<br><br>";
die;

请注意,Creating new instance of ConcreteClass Setting: ->prop1 = new DummyClass(array ( 'foo' => 'abc123', )) Created TestClass1... Creating new instance of ConcreteClass Setting: ->prop1 = new abc123def456(array ( 'boo' => 'abc123def456', )) Error: assert(): abc123def456 !== DummyClass failed 的值为$propClass,这是怎么发生的?

更古怪

  • 将“ abc123def456”的值更改为“ 12345678”,它将起作用。
  • 将“ abc123def456”的值更改为“ 123456789”,它将不起作用。
  • 省略var_export(),它将起作用。 (不过,在其他情况下它可能仍然会中断)。

我的直觉告诉我这是一个PHP错误,但我可能做错了,和/或可能在某处记录了该错误。我想澄清一下,因为到目前为止,我唯一可靠的解决方案是不缓存反映的$ publicProps。这样一来,每次我创建新的abc123def456时都会避免不必要地调用ReflectionClass->getProperties()

1 个答案:

答案 0 :(得分:1)

结果证明这是PHP中的错误:https://bugs.php.net/bug.php?id=79820

此处的复制量最少:https://3v4l.org/kchfm

已在7.4.9中修复:https://www.php.net/ChangeLog-7.php#7.4.9