PHP - PHP Reflection API
Introduction
The PHP Reflection API is a built-in feature of PHP that allows a program to examine and inspect its own classes, objects, methods, properties, functions, parameters, and other program structures at runtime.
Normally, PHP programs know the structure of a class because the developer has written the class definition. Reflection provides a way to discover that information dynamically while the program is running.
For example, suppose a PHP application receives the name of a class as a string. Without Reflection, it can be difficult to determine:
-
What methods does the class contain?
-
What properties does it contain?
-
Which methods are public, private, or protected?
-
What parameters does a method accept?
-
What types do those parameters require?
-
Does the class extend another class?
-
Does it implement a particular interface?
-
What attributes are attached to the class or method?
The Reflection API provides classes and methods that can answer these questions programmatically.
1. Why Reflection Is Used
Reflection is particularly useful when an application needs to work with classes without knowing their complete structure in advance.
Consider this class:
class Student
{
private string $name;
public int $age;
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
}
A normal program can directly call:
$student = new Student();
$student->setName("Rahul");
echo $student->getName();
However, suppose another program needs to discover the structure of Student dynamically.
It can use Reflection:
$reflection = new ReflectionClass(Student::class);
echo $reflection->getName();
Output:
Student
The program did not manually inspect the source code. PHP provided the class information through Reflection.
2. ReflectionClass
The most commonly used Reflection class is ReflectionClass.
It provides information about a PHP class.
Basic syntax:
$reflection = new ReflectionClass(ClassName::class);
Example:
class Employee
{
public string $name;
public function work(): void
{
echo "Employee is working";
}
}
$reflection = new ReflectionClass(Employee::class);
echo $reflection->getName();
Output:
Employee
ReflectionClass can provide information about:
-
Class name
-
Parent class
-
Interfaces
-
Traits
-
Methods
-
Properties
-
Constants
-
Attributes
-
Modifiers
-
Constructor
-
Instantiability
3. Getting Class Name
The getName() method returns the name of the class.
class Product
{
}
$reflection = new ReflectionClass(Product::class);
echo $reflection->getName();
Output:
Product
This is useful when the class is supplied dynamically.
4. Checking Whether a Class Exists
Reflection can be combined with class_exists().
if (class_exists("Product")) {
$reflection = new ReflectionClass("Product");
echo $reflection->getName();
}
This prevents the application from attempting to reflect a class that does not exist.
5. Inspecting Class Methods
The getMethods() method returns information about the methods declared or inherited by a class.
Example:
class Calculator
{
public function add()
{
}
public function subtract()
{
}
}
$reflection = new ReflectionClass(Calculator::class);
$methods = $reflection->getMethods();
foreach ($methods as $method) {
echo $method->getName() . PHP_EOL;
}
Output will include:
add
subtract
Each returned object is an instance of ReflectionMethod.
6. Inspecting a Specific Method
You can inspect one particular method using getMethod().
class User
{
public function login(string $username, string $password): bool
{
return true;
}
}
$reflection = new ReflectionClass(User::class);
$method = $reflection->getMethod("login");
echo $method->getName();
Output:
login
The ReflectionMethod object provides additional information about the method.
7. Inspecting Method Parameters
Reflection is particularly useful for discovering the parameters accepted by a method.
Example:
class User
{
public function login(string $username, string $password): bool
{
return true;
}
}
$reflection = new ReflectionClass(User::class);
$method = $reflection->getMethod("login");
$parameters = $method->getParameters();
foreach ($parameters as $parameter) {
echo $parameter->getName() . PHP_EOL;
}
Output:
username
password
The application can therefore discover the parameter names without manually reading the source code.
8. Getting Parameter Types
Reflection can also determine the expected type of a parameter.
foreach ($method->getParameters() as $parameter) {
echo $parameter->getName() . ": ";
$type = $parameter->getType();
if ($type !== null) {
echo $type;
}
echo PHP_EOL;
}
Possible output:
username: string
password: string
This is useful for systems that need to automatically understand how a method should be called.
9. Inspecting Return Types
Reflection can also determine the return type of a method.
$method = $reflection->getMethod("login");
$returnType = $method->getReturnType();
echo $returnType;
Output:
bool
This allows a program to determine that the login() method is expected to return a Boolean value.
10. Inspecting Properties
The getProperties() method retrieves information about class properties.
Example:
class Customer
{
private string $name;
public int $age;
}
$reflection = new ReflectionClass(Customer::class);
$properties = $reflection->getProperties();
foreach ($properties as $property) {
echo $property->getName() . PHP_EOL;
}
Output:
name
age
Each property is represented by a ReflectionProperty object.
11. Inspecting Property Visibility
Reflection can determine whether a property is public, protected, or private.
foreach ($reflection->getProperties() as $property) {
echo $property->getName() . ": ";
if ($property->isPublic()) {
echo "Public";
} elseif ($property->isProtected()) {
echo "Protected";
} elseif ($property->isPrivate()) {
echo "Private";
}
echo PHP_EOL;
}
For the previous example, the output would be similar to:
name: Private
age: Public
This is useful for tools that need to understand class structure automatically.
12. Inspecting the Parent Class
Reflection can determine whether a class extends another class.
class Animal
{
}
class Dog extends Animal
{
}
$reflection = new ReflectionClass(Dog::class);
$parent = $reflection->getParentClass();
if ($parent !== false) {
echo $parent->getName();
}
Output:
Animal
This allows applications to inspect inheritance relationships.
13. Checking Implemented Interfaces
A class can implement one or more interfaces.
interface Payment
{
}
class CreditCardPayment implements Payment
{
}
Reflection can determine which interfaces are implemented.
$reflection = new ReflectionClass(CreditCardPayment::class);
$interfaces = $reflection->getInterfaces();
foreach ($interfaces as $interface) {
echo $interface->getName();
}
Output:
Payment
This can be useful in plugin systems and dependency-management systems.
14. Inspecting Traits
PHP classes can use traits.
trait Logger
{
public function log()
{
echo "Logging";
}
}
class Application
{
use Logger;
}
Reflection can identify the traits used by the class.
$reflection = new ReflectionClass(Application::class);
$traits = $reflection->getTraits();
foreach ($traits as $trait) {
echo $trait->getName();
}
Output:
Logger
15. Inspecting Class Modifiers
Reflection can determine whether a class is:
-
Abstract
-
Final
-
Instantiable
-
Internal
-
Anonymous
For example:
abstract class Animal
{
}
You can check:
$reflection = new ReflectionClass(Animal::class);
if ($reflection->isAbstract()) {
echo "The class is abstract.";
}
Output:
The class is abstract.
Similarly:
if ($reflection->isFinal()) {
echo "The class is final.";
}
16. Inspecting Constructors
Reflection can also inspect the constructor of a class.
class Employee
{
public function __construct(
string $name,
int $id
) {
}
}
You can retrieve the constructor:
$reflection = new ReflectionClass(Employee::class);
$constructor = $reflection->getConstructor();
if ($constructor !== null) {
foreach ($constructor->getParameters() as $parameter) {
echo $parameter->getName() . PHP_EOL;
}
}
Output:
name
id
This capability is important in dependency injection systems.
17. Dynamically Creating Objects
Reflection can also be used to create objects.
For example:
class Product
{
public function __construct(string $name)
{
echo "Product: " . $name;
}
}
$reflection = new ReflectionClass(Product::class);
$product = $reflection->newInstance("Laptop");
The class is instantiated through Reflection rather than directly using:
new Product("Laptop");
This becomes useful when the class name and constructor information are determined dynamically.
18. ReflectionMethod
ReflectionMethod focuses specifically on methods.
Example:
class Calculator
{
public function add(int $a, int $b): int
{
return $a + $b;
}
}
$method = new ReflectionMethod(Calculator::class, "add");
echo $method->getName();
Output:
add
It can also provide:
-
Method parameters
-
Return type
-
Visibility
-
Static status
-
Abstract status
-
Final status
-
Attributes
19. Invoking Methods Dynamically
Reflection can invoke a method dynamically.
class Calculator
{
public function add(int $a, int $b): int
{
return $a + $b;
}
}
$calculator = new Calculator();
$method = new ReflectionMethod(Calculator::class, "add");
$result = $method->invoke($calculator, 10, 20);
echo $result;
Output:
30
Here, the method name can be determined dynamically rather than being directly written as:
$calculator->add(10, 20);
This capability is useful in frameworks, testing tools, command systems, and dynamic application architectures.
20. ReflectionFunction
Reflection is not limited to classes and methods. PHP also provides ReflectionFunction for inspecting functions.
Example:
function calculate(int $a, int $b): int
{
return $a + $b;
}
$reflection = new ReflectionFunction("calculate");
echo $reflection->getName();
Output:
calculate
Parameters can also be inspected:
foreach ($reflection->getParameters() as $parameter) {
echo $parameter->getName() . PHP_EOL;
}
Output:
a
b
21. ReflectionObject
ReflectionObject is used when you want to inspect a specific object.
Example:
class Customer
{
public string $name = "John";
}
$customer = new Customer();
$reflection = new ReflectionObject($customer);
echo $reflection->getName();
Output:
Customer
It provides information about the actual object while it is running.
22. Reflection and Dependency Injection
One important practical use of Reflection is dependency injection.
Consider:
class Database
{
}
class UserRepository
{
public function __construct(Database $database)
{
}
}
A dependency injection container can inspect the constructor:
$reflection = new ReflectionClass(UserRepository::class);
$constructor = $reflection->getConstructor();
foreach ($constructor->getParameters() as $parameter) {
$type = $parameter->getType();
echo $type;
}
The container can discover that UserRepository requires a Database object.
Frameworks can use this information to construct objects and supply their dependencies automatically.
23. Reflection in Testing
Testing frameworks can use Reflection to discover test methods or inspect classes.
For example, a testing system could examine a class and find methods that follow a particular naming convention.
$reflection = new ReflectionClass(MyTest::class);
foreach ($reflection->getMethods() as $method) {
if (str_starts_with($method->getName(), "test")) {
echo $method->getName() . PHP_EOL;
}
}
A testing system could then execute the discovered methods.
24. Reflection in Frameworks
Many PHP frameworks and libraries need to understand application classes dynamically.
Reflection can help frameworks:
-
Discover dependencies
-
Inspect constructors
-
Identify methods
-
Read parameter types
-
Inspect attributes
-
Create objects
-
Invoke methods
-
Build dependency graphs
For example, a framework may receive:
class OrderController
{
public function __construct(OrderService $service)
{
}
}
The framework can inspect the constructor and determine that OrderService needs to be supplied.
This reduces the amount of manual configuration required by developers.
25. Reflection and Attributes
Modern PHP supports attributes that can provide metadata.
For example:
#[Route("/users")]
class UserController
{
}
Reflection can inspect this attribute.
$reflection = new ReflectionClass(UserController::class);
$attributes = $reflection->getAttributes();
foreach ($attributes as $attribute) {
echo $attribute->getName();
}
Output:
Route
A framework can use this information to automatically configure routes, commands, services, or other application components.
26. ReflectionException
Reflection operations can produce exceptions when the requested class, method, or property does not exist.
Example:
try {
$reflection = new ReflectionClass("UnknownClass");
} catch (ReflectionException $e) {
echo "Reflection failed: " . $e->getMessage();
}
Using exception handling makes the application more reliable when working with dynamic class information.
27. Advantages of Reflection
Reflection provides several important advantages.
Dynamic Inspection
Programs can discover class and method information at runtime.
Framework Development
Reflection is useful when building dependency injection containers, routing systems, ORMs, testing frameworks, and plugin systems.
Reduced Manual Configuration
Applications can automatically discover dependencies and metadata.
Better Development Tools
IDEs, debugging tools, documentation generators, and testing tools can use reflection-like information to understand PHP code.
Flexible Object Creation
Objects can be created dynamically when the class and constructor information are not known beforehand.
28. Limitations of Reflection
Reflection should not be used everywhere.
It can make applications more complex because the program becomes dependent on dynamically discovered information.
There can also be performance overhead when Reflection is repeatedly performed during application execution.
For example, repeatedly inspecting the same class is generally unnecessary. A framework may therefore cache Reflection information.
Reflection can also make code harder to understand if it replaces straightforward method calls and object creation without a genuine need.
29. Reflection Compared with Normal PHP Code
Normal approach:
$user = new User();
$user->login("rahul", "12345");
The developer already knows the class and method.
Reflection-based approach:
$reflection = new ReflectionClass(User::class);
$method = $reflection->getMethod("login");
$result = $method->invoke(
$user,
"rahul",
"12345"
);
The second approach is more dynamic, but it is also more complex.
Therefore, Reflection is most valuable when the application genuinely needs runtime inspection or dynamic behavior.
30. Complete Example
The following example demonstrates several Reflection features together:
class Employee
{
private string $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function greet(string $message): string
{
return $message . ", " . $this->name;
}
}
$reflection = new ReflectionClass(Employee::class);
echo "Class: " . $reflection->getName() . PHP_EOL;
echo "Properties:" . PHP_EOL;
foreach ($reflection->getProperties() as $property) {
echo $property->getName() . PHP_EOL;
}
echo "Methods:" . PHP_EOL;
foreach ($reflection->getMethods() as $method) {
echo $method->getName() . PHP_EOL;
}
$constructor = $reflection->getConstructor();
if ($constructor !== null) {
echo "Constructor Parameters:" . PHP_EOL;
foreach ($constructor->getParameters() as $parameter) {
echo $parameter->getName() . PHP_EOL;
}
}
This program dynamically discovers information about the Employee class.
It can identify:
Class: Employee
Properties:
name
Methods:
__construct
greet
Constructor Parameters:
name
The important point is that the program is obtaining this structural information through the Reflection API rather than manually maintaining a separate description of the class.
Conclusion
The PHP Reflection API provides a powerful mechanism for examining PHP classes, objects, methods, properties, functions, parameters, return types, interfaces, traits, constructors, and attributes at runtime.
The major Reflection classes include:
| Reflection Class | Purpose |
|---|---|
ReflectionClass |
Inspects classes |
ReflectionMethod |
Inspects class methods |
ReflectionProperty |
Inspects class properties |
ReflectionFunction |
Inspects functions |
ReflectionObject |
Inspects objects |
ReflectionParameter |
Inspects function or method parameters |
Reflection is especially important when developing frameworks, dependency injection containers, testing systems, plugin architectures, routing systems, object factories, and developer tools.
For ordinary application code, direct class and method calls are usually simpler. Reflection becomes valuable when the program needs to discover or manipulate PHP structures dynamically at runtime.