Reflection is the mechanism implemented mostly in (dynamic) languages, giving the ability to a computer program to inspect itself and modify its structure and behavior (properties, methods, types of objects) at runtime without knowing the names of the interfaces, fields, and methods at compile time.
Reflection, as an object-oriented paradigm, can be used in:
- Code debugging
- Making generic software libraries to display data
- Creating documentation
- As part of software testing
- Allows instantiation of new objects and invocation of methods
PHP’s Reflection API is a core API, which means no extra installation is required (other than the PHP itself). It consists of built-in classes for analyzing properties, methods, to help us master new skills, cope with incomplete knowledge, examine assumptions, review our experiences, plan, check for consistency and recover from mistakes.
This mechanism is similar in some respects to existing object functions, such as get_class_vars(), but it is more flexible and provides much greater detail. Also, it is designed to work with PHP’s object-oriented features, such as access control, interfaces, and abstract classes.
It does not exist as a single function or class, rather, it exists as a set of classes, whose names all start with Reflection, and the term following it indicates what type of structure it can “reflect”.
Table 1. List of classes in the Reflection API
Class | Description |
Reflection | Provides a static export() method for summarizing class information |
ReflectionClass | Class information and tools |
ReflectionMethod | Class method information and tools |
ReflectionParameter | Method argument information |
ReflectionProperty | Class property information |
ReflectionFunction | Function information and tools |
ReflectionExtension | PHP extension information |
ReflectionException | An error class |
(The full list of classes can be found on php.net)
For object-oriented programming languages, the Reflection API’s power and reach mean we should usually use it in preference to the class and object functions. It can be found as an indispensable tool for testing classes, while generating class diagrams or documentation, for example, or when saving object information to a database, examining an object’s accesses (getters and setters) methods to extract field names. Another use of Reflection is building a framework that invokes methods in module classes according to a naming scheme.
Simple examples:
1. Getting class information, methods, and properties
ExampleClass, provides some simple methods and attributes, also it represents a starting point in the next examples.
The Reflection::export() method provides a lot of useful information for debugging and makes it possible to analyze the properties of ExampleClass, from the outside.
Reflection class Object provides information about class methods and properties, the output can also be defined as needed.
2. Nested classes
When using ReflectionClass::export() method on nested classes (ChildClass), we get information about all the public, protected and private methods and properties in ChildClass and all the public and protected methods and properties in the inherited class.
If the __construct() method is overwritten in ChildClass, we get that information, too.
3. Abstract classes and interfaces
Abstraction and interfaces are two very different tools. Abstract classes may have implemented methods, where interfaces have no implementation in themselves.
With ReflectionClass::isAbstract() we can check if the class is abstract. Just as ReflectionClass is used to examine a class, a ReflectionMethod object examines a method, and it can be checked if the method is abstract.
For working with interfaces, ReflectionClass::isInterface() returns if a class is an interface, or false if not. ReflectionClass::getInterfaces() returns an associative array of interfaces, with keys as interface names and the array values as ReflectionClass objects. There are plenty of functions and methods from which we can get the desired information.
ReflectionProperty::setValue() is used to set the value on static properties as well as regular instance properties. It throws exception if the property is inaccessible (protected or private). It can be used on protected and private properties if ReflectionProperty::setAccessible() was invoked, before ReflectionProperty::setValue().
Getting the namespace name where each class/object lives can be achieved from ReflectionClass::getNamespaceName(). This returns a string, or if the object does not belong to a namespace, an empty string is returned.
ReflectionClass::getParentClass() can return a ReflectionClass object of the parent class or false if no parent.
ReflectionClass::hasMethod () checks if the current class has a method with name as the argument.
Conclusion:
The Reflection API represents a very powerful technology that can really help you accomplish code inspection, debugging and code manipulation. It has a very board-spectrum of functions, methods and any area of the OOP structures can be easily reached.
Reference:
- PHP Objects, Patterns, and Practice – Fifth Edition
- https://docs.hhvm.com/hack/reference/class/ReflectionMethod/
- https://www.php.net/manual/en/book.reflection.php