Does ReflectionClass::getProperties() also get pro

2019-06-22 12:39发布

问题:

I am trying to access/change the properties of a class' Parent through Reflection.

If I run ReflectionClass::getProperties() on the child, does it also return any properties that the Parent has as well?

If it doesn't, is there any way to access the parent properties using Reflection?

回答1:

I worked up this quick test. It looks like private properties of the parent are hidden when you get the child classes's properties. However, if you invoke getParentClass() then getProperties() you will have the missing set of private props.

<?php
class Ford { 
  private $model;
  protected $foo;
  public $bar;
}

class Car extends Ford {
  private $year;
}

$class = new ReflectionClass('Car');
var_dump($class->getProperties()); // First chunk of output
var_dump($class->getParentClass()->getProperties()); // Second chunk

Output (notice the private prop Ford::model is missing):

array(3) {
  [0]=>
  &object(ReflectionProperty)#2 (2) {
    ["name"]=>
    string(4) "year"
    ["class"]=>
    string(3) "Car"
  }
  [1]=>
  &object(ReflectionProperty)#3 (2) {
    ["name"]=>
    string(3) "foo"
    ["class"]=>
    string(4) "Ford"
  }
  [2]=>
  &object(ReflectionProperty)#4 (2) {
    ["name"]=>
    string(3) "bar"
    ["class"]=>
    string(4) "Ford"
  }
}

Second Chunk (contains all the properties of the Ford class):

array(3) {
  [0]=>
  &object(ReflectionProperty)#3 (2) {
    ["name"]=>
    string(5) "model"
    ["class"]=>
    string(4) "Ford"
  }
  [1]=>
  &object(ReflectionProperty)#2 (2) {
    ["name"]=>
    string(3) "foo"
    ["class"]=>
    string(4) "Ford"
  }
  [2]=>
  &object(ReflectionProperty)#5 (2) {
    ["name"]=>
    string(3) "bar"
    ["class"]=>
    string(4) "Ford"
  }
}


回答2:

Though succinct, the accepted answer neglects the possibility of a child class with many ancestors. This is the instance method I use to achieve this:

public function getProperties() {
    $properties = array();
    try {
        $rc = new \ReflectionClass($this);
        do {
            $rp = array();
            /* @var $p \ReflectionProperty */
            foreach ($rc->getProperties() as $p) {
                $p->setAccessible(true);
                $rp[$p->getName()] = $p->getValue($this);
            }
            $properties = array_merge($rp, $properties);
        } while ($rc = $rc->getParentClass());
    } catch (\ReflectionException $e) { }
    return $properties;
}

It traverses up the hierarchy until it reaches the root class, while merging the properties of each parent with the properties of its children (and in the case of defaults, uses only the defaults found in the lowermost part of the hierarchy).



回答3:

I think you won't get the parent private properties because the child class can't access them