Reflection in Depth
Reflection can also act on a class, not only describe it. It can call methods, build objects and read private properties.
A method called through reflection
The hello method of the Greeter class is fetched as a reflection method. The invoke call runs it on the object with one argument, and the greeting prints.
<?php
class Greeter {
public function hello($name) {
return "Hello, " . $name;
}
}
$g = new Greeter();
$ref = new ReflectionClass(Greeter::class);
$method = $ref->getMethod("hello");
echo $method->invoke($g, "Ana") . "\n";An object built with newInstance
The newInstance call on the ReflectionClass builds a Book and passes two constructor arguments. A method on the built object prints its line.
<?php
class Book {
public function __construct(
public string $title,
public string $author
) {
}
public function line() {
return $this->title . " by " . $this->author;
}
}
$ref = new ReflectionClass(Book::class);
$book = $ref->newInstance("Dune", "Herbert");
echo $book->line() . "\n";A private property read from outside
The secret property of the Vault class is private. A ReflectionProperty reads its value from outside the class, and the secret prints.
<?php
class Vault {
private string $secret = "open-sesame";
}
$v = new Vault();
$prop = new ReflectionProperty(Vault::class, "secret");
echo $prop->getValue($v) . "\n";Parent and subclass verdicts
The Dog class extends the Animal class. The subclass verdict prints as a bool, and the parent name comes from the reflection of the child.
<?php
class Animal {
}
class Dog extends Animal {
}
var_dump(is_subclass_of(Dog::class, Animal::class));
$ref = new ReflectionClass(Dog::class);
echo $ref->getParentClass()->getName() . "\n";Example
<?php
class Shape {
public function kind() {
return "shape";
}
}
class Circle extends Shape {
public function kind() {
return "circle";
}
}
function inspect($obj) {
$ref = new ReflectionClass($obj);
echo $ref->getName() . "\n";
echo $ref->getParentClass()->getName() . "\n";
$method = $ref->getMethod("kind");
echo $method->invoke($obj) . "\n";
}
inspect(new Circle());Key points
- The getMethod method returns one method ready to be called.
- The invoke method calls that method on a given object.
- The newInstance method on a ReflectionClass builds an object with given constructor arguments.
- A ReflectionProperty object can read a private property from outside the class.
- The getParentClass method returns the parent class of a child class.
In this example, the inspect function takes one object and reports on it. Reflection prints the class name first and the parent class name next. The kind method is then called through reflection, and its result prints last.
Note
Private state stays private for normal code, and reflection is the deliberate exception to that rule.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
How can code outside a class read a private property of an object?