Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does ReflectionClass::getProperties() also get properties of the parent?

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?

like image 704
johnnietheblack Avatar asked Mar 28 '12 18:03

johnnietheblack


People also ask

Which function get the default properties of the class?

The ReflectionClass::getDefaultProperties() function is an inbuilt function in PHP which is used to return the default properties including inherited properties from a specified class.

What is ReflectionClass PHP?

The reflection class is used to get information about the current state of the application. It's called reflection, because it looks at it's self, and can tell you information about the program your running, at run time.


2 Answers

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"
  }
}
like image 132
Mike B Avatar answered Oct 05 '22 17:10

Mike B


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).

like image 31
NobleUplift Avatar answered Oct 05 '22 17:10

NobleUplift