The reflection API in PHP is just like the java.lang.Reflect package in Java. It consists of a series of built-in classes that analyze properties, methods, and classes. It is similar to object functions in some ways, such as get_class_vars(), but is more flexible and can provide more information. The reflection API also works with THE latest object-oriented features of PHP, such as access control, interfaces, and abstract classes. Older class functions are less easy to use with these new features. Those of you who have seen the source code of the framework should have some understanding of the reflection mechanism of PHP, such as dependency injection, object pooling, class loading, some design patterns, etc., all use reflection mechanism.
1. Partial classes of the reflection API
class | describe |
Reflection | Provide the static function export() for class summary information |
ReflectionClass | Class information and tools |
ReflectionMethod | Class method information and tools |
ReflectionParameter | Method Parameter Information |
ReflectionProperty | Class attribute information |
ReflectionFunction | Function information and tools |
ReflectionExtension | PHP Extension Information |
ReflectionException | The wrong class |
Using the reflection API classes, we can get information about how to access extensions in objects, functions, and scripts at run time. This information can be used to analyze classes or build frameworks.
2. Get information about the class
We have used several functions in our work to check class attributes, such as get_class_methods, getProduct, and so on. These methods have significant limitations for obtaining detailed class information.
We can do this by reflecting API classes: The static method export provided by Reflection and ReflectionClass is used to obtain information about a class. Export provides almost all the information about a class, including the access control status of attributes and methods, the parameters required for each method, and the location of each method in the script document. The output of the export static method is the same for the two utility classes, but is used differently.
First, build a simple class
1 <? php 2 3 class Student { 4 public $name; 5 protected $age; 6 private $sex; 7 8 public function __construct($name, $age, $sex) 9 { 10 $this->setName($name); 11 $this->setAge($age); 12 $this->setSex($sex); 13 } 14 15 public function setName($name) 16 { 17 $this->name = $name; 18 } 19 20 protected function setAge($age) 21 { 22 $this->age = $age; 23 } 24 25 private function setSex($sex) 26 { 27 $this->sex = $sex; 28}} 29Copy the code
2.1 Use ReflectionClass::export() to obtain class information
ReflectionClass::export('Student');Copy the code
Print result:
Class [ class Student ] { @@ D:\wamp\www\test2.php 3-29 - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [3] { Property [ public $name ] Property [ protected $age ] Property [ private $sex ] } - Methods [4] { Method [ public method __construct ] { @@ D:\wamp\www\test2.php 8 - 13 - Parameters [3] { Parameter #0 [ $name ] Parameter #1 [ $age ] Parameter #2 [ $sex ] } } Method [ public method setName ] { @@ D:\wamp\www\test2.php 15 - 18 - Parameters [1] { Parameter #0 [ $name ] } } Method [ protected method setAge ] { @@ D:\wamp\www\test2.php 20 - 23 - Parameters [1] { Parameter #0 [ $age ] } } Method [ private method setSex ] { @@ D:\wamp\www\test2.php 25 - 28 - Parameters [1] { Parameter #0 [ $sex ] } } } }Copy the code
The ReflectionClass class provides a number of tools and methods. The official manual lists them as follows:
ReflectionClass: : __construct - initializes the ReflectionClass class ReflectionClass: : export - a derived class ReflectionClass: : getConstant - For defined a constant ReflectionClass: : ReflectionClass getConstants - to obtain a set of constants: : getConstructor - access to the constructor of a class ReflectionClass: : getDefaultProperties - get default attributes ReflectionClass: : getDocComment - get the document comment ReflectionClass: : getEndLine - For the last line of the number of rows ReflectionClass: : getExtension - according to the defined ReflectionClass class takes place extended ReflectionExtension object: : getExtensionName - For the expansion of the classes defined in the name of the ReflectionClass: : filename ReflectionClass getFileName - access to define the class: : getInterfaceNames - access interface (interface) name ReflectionClass: : getInterfaces - access interface ReflectionClass: : getMethod ReflectionMethod - get a class method. ReflectionClass ReflectionClass: : getMethods - acquisition method of array: : getModifiers - get the modifier ReflectionClass class: : getName - get the name of the class ReflectionClass: : getNamespaceName - for namespace name ReflectionClass: : getParentClass - get the superclass ReflectionClass: : getProperties - Get a set of attributes ReflectionClass: : getProperty - get a property of a class of ReflectionProperty ReflectionClass: : getReflectionConstant - Gets a ReflectionClassConstant for a class 's constant ReflectionClass: : getReflectionConstants - Gets the class constants ReflectionClass: : getShortName - for short name ReflectionClass: : getStartLine - get starting line number ReflectionClass: : getStaticProperties - For static (static) attribute ReflectionClass: : getStaticPropertyValue static (static) - get the value of the attribute ReflectionClass: : getTraitAliases - returns the trait Alias ReflectionClass: an array: getTraitNames - returns the name of the traits of this class are using array ReflectionClass: : getTraits - returns the traits used by this class array ReflectionClass: : hasConstant - check to see if the constants has been defined ReflectionClass: : hasMethod - check methods defined ReflectionClass: : hasProperty - Check whether the attribute is defined ReflectionClass: : implementsInterface - the implementation of the interface ReflectionClass: : inNamespace - check whether in the namespace ReflectionClass: : isAbstract - check class is an abstract class (abstract) ReflectionClass: : isAnonymous - check whether class is an anonymous class ReflectionClass: : isCloneable - returns a class whether can copy the ReflectionClass: : isFinal - check whether the class is declared as final ReflectionClass: : isInstance - check the instance of the class ReflectionClass: : isInstantiable - check to see if the class can be instantiated ReflectionClass: : isInterface - check whether a class (interface) ReflectionClass: : isInternal - check whether the class is defined by the extension or core in internal ReflectionClass: : isIterateable - check whether can be iterative (iterateable) ReflectionClass: : isSubclassOf - check for a subclass ReflectionClass: : isTrait - returns whether it is a trait ReflectionClass: : isUserDefined - Check whether the ReflectionClass defined by the user: : newInstance - from the specified parameters to create a new class instance ReflectionClass: : newInstanceArgs - from the given parameters to create a new class instance. ReflectionClass: : newInstanceWithoutConstructor - create a new class instance and not call its constructor ReflectionClass: : setStaticPropertyValue - set the value of static properties ReflectionClass::__toString - Returns the string representation of the ReflectionClass object.Copy the code
2.2 Use Reflection::export() to obtain the class information
$prodClass = new ReflectionClass('Student');
Reflection::export($prodClass);Copy the code
Print the result
Class [ class Student ] { @@ D:\wamp\www\test2.php 3-29 - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [3] { Property [ public $name ] Property [ protected $age ] Property [ private $sex ] } - Methods [4] { Method [ public method __construct ] { @@ D:\wamp\www\test2.php 8 - 13 - Parameters [3] { Parameter #0 [ $name ] Parameter #1 [ $age ] Parameter #2 [ $sex ] } } Method [ public method setName ] { @@ D:\wamp\www\test2.php 15 - 18 - Parameters [1] { Parameter #0 [ $name ] } } Method [ protected method setAge ] { @@ D:\wamp\www\test2.php 20 - 23 - Parameters [1] { Parameter #0 [ $age ] } } Method [ private method setSex ] { @@ D:\wamp\www\test2.php 25 - 28 - Parameters [1] { Parameter #0 [ $sex ] } } } }Copy the code
Once the ReflectionClass object is created, you can use the Reflection utility class to output information about the Student class. Reflection::export() can format and output instances of any class that implements the Reflector interface.
3. Check the class
We learned earlier about the ReflectionClass utility class, which provides a number of utility methods for retrieving information about the class. For example, we can get the type of the Student class and see if it can be instantiated
Tool function
function classData(ReflectionClass $class) { $details = ''; $name = $class->getName(); If ($class->isUserDefined()) {$details.= "$name is user defined". } if ($class->isInternal()) {$details.= "$name is built-in". $details.= "$name is interface". PHP_EOL; $details.= "$name is an abstract class". PHP_EOL; } if ($class->isFinal()) {// if ($class->isFinal()) {$details.= "$name is a final class". If ($class->isInstantiable()) {$details.= "$name can be instantiated". } else { $details .= "$name can not be instantiated" . PHP_EOL; } return $details; } $prodClass = new ReflectionClass('Student'); print classData($prodClass);Copy the code
Print the result
Student is user defined
Student can be instantiatedCopy the code
In addition to getting information about the class, you can also get source information about the name of the custom class and the start and end lines of the class in the file provided by the ReflectionClass object.
function getClassSource(ReflectionClass $class) { $path = $class->getFileName(); $lines = @file($path); $from = $class->getStartLine(); $to = $class->getEndLine(); $len = $to - $from + 1; return implode(array_slice($lines, $from - 1, $len)); } $prodClass = new ReflectionClass('Student'); var_dump(getClassSource($prodClass));Copy the code
Print the result
string 'class Student {
public $name;
protected $age;
private $sex;
public function __construct($name, $age, $sex)
{
$this->setName($name);
$this->setAge($age);
$this->setSex($sex);
}
public function setName($name)
{
$this->name = $name;
}
protected function setAge($age)
{
$this->age = $age;
}
private function setSex($sex)
{
$this->sex = $sex;
}
}
' (length=486)Copy the code
We see that getClassSource takes a ReflectionClass object as its argument and returns the source code for the corresponding class. This function ignores error handling and should actually check the argument and result code!
4. Check methods
Similar to examining a class, the ReflectionMethod object can be used to examine methods in a class.
There are two ways to get a ReflectionMethod object:
The first is through ReflectionClass: : getMethods () to obtain the ReflectionMethod object array, the benefits of this approach is not know in advance the method name, return all the methods in the class of the ReflectionMethod object.
The second method is to use the ReflectionMethod class directly to instantiate the object. In this way, you can only get one class method object, so you need to know the method name in advance.
The tool method of the ReflectionMethod object:
ReflectionMethod: : __construct - ReflectionMethod constructor ReflectionMethod: : export output - a callback method ReflectionMethod: : getClosure - Returns a dynamically created method call interface. You can use this return value to call a private method directly. ReflectionMethod: : getDeclaringClass - for reflection function call parameters express ReflectionMethod class: : getModifiers - access method of the modifier ReflectionMethod: : getPrototype - method returns the prototype (if present) ReflectionMethod: : invoke - invoke ReflectionMethod: : invokeArgs - with parameters is carried out ReflectionMethod: : isAbstract - judgment method is abstract methods ReflectionMethod: : isConstructor - method to construct judgment method is ReflectionMethod: : isDestructor - judgment method is a destructor ReflectionMethod: : isFinal - to determine whether a method to define the final ReflectionMethod: : isPrivate - judgment method is a private method ReflectionMethod: : isProtected - judgment method is to protect method (protected) ReflectionMethod: : isPublic - judgment method is public methods ReflectionMethod: : isStatic - judgment method is a static method ReflectionMethod: : setAccessible - setting method whether access ReflectionMethod: : __toString - Returns a string representation of the reflection method objectCopy the code
ReflectionClass: 4.1: getMethods ()
We can through the ReflectionClass: : getMethods () to obtain ReflectionMethod array of objects.
$prodClass = new ReflectionClass('Student');
$methods = $prodClass->getMethods();
var_dump($methods);Copy the code
Print the result
array (size=4)
0 => &
object(ReflectionMethod)[2]
public 'name' => string '__construct' (length=11)
public 'class' => string 'Student' (length=7)
1 => &
object(ReflectionMethod)[3]
public 'name' => string 'setName' (length=7)
public 'class' => string 'Student' (length=7)
2 => &
object(ReflectionMethod)[4]
public 'name' => string 'setAge' (length=6)
public 'class' => string 'Student' (length=7)
3 => &
object(ReflectionMethod)[5]
public 'name' => string 'setSex' (length=6)
public 'class' => string 'Student' (length=7)Copy the code
As you can see, we get the Student array of ReflectionMethod objects. Each element is an object with two common attributes: name is the method name and class is the parent class. We can call object methods to get method information.
4.2 ReflectionMethod
Use the ReflectionMethod class directly to get information about class methods
$method = new ReflectionMethod('Student', 'setName');
var_dump($method);Copy the code
Print the result
object(ReflectionMethod)[1]
public 'name' => string 'setName' (length=7)
public 'class' => string 'Student' (length=7)Copy the code
4.3 pay attention to
In PHP5, if the check method returns only object (even if the object is by referencing assignment or transfer), then the ReflectionMethod: : retursReference () returns true. Only when the detection method has been explicitly stated return reference (in front of the method name & symbols), ReflectionMethod: : returnsReference () to return true.
5. Check method parameters
In PHP5, class methods can be declared with restrictions on the types of objects in their arguments, so checking method arguments becomes necessary.
Similar to checking methods, the ReflectionParameter object can be used to check methods in a class. It can tell you the name of the parameter, whether the variable can be passed by reference, the parameter type hint, and whether the method accepts null values as arguments.
There are also two ways to get a ReflectionParameter object, which is very similar to getting a ReflectionMethod object:
The first is through ReflectionMethod: : getParameters () method returns ReflectionParameter array of objects, this method can obtain all the parameter object to a method.
The second method is to instantiate the object directly using the ReflectionParameter class. This method can only fetch objects with a single parameter.
Tool methods for the ReflectionParameter object:
ReflectionParameter: : allowsNull - Checks if null charges ReflectionParameter: : canBePassedByValue - Returns been This parameter can be passed by value ReflectionParameter::__clone - Clone ReflectionParameter::__construct - Construct ReflectionParameter: : export - Exports ReflectionParameter: : getClass - Get the type hinted the class ReflectionParameter: : getDeclaringClass - Gets declaring class ReflectionParameter: : getDeclaringFunction - Gets declaring The function ReflectionParameter: : getDefaultValue - Gets the default parameter value ReflectionParameter: : getDefaultValueConstantName - Returns the default value 's constant name if the default value is Constant or null ReflectionParameter: : getName - Gets parameter name ReflectionParameter: : getPosition - Gets the parameter The position ReflectionParameter: : getType - Gets a parameter 's type ReflectionParameter: : hasType - Checks if the parameter has a Type ReflectionParameter: : isArray - Checks if the parameter expects an array ReflectionParameter: : isCallable - Returns Been parameter MUST be callable ReflectionParameter: : isDefaultValueAvailable - Checks if a default value is available ReflectionParameter: : isDefaultValueConstant - Returns been the default value of this parameter is a constant ReflectionParameter: : isOptional - Checks if optional ReflectionParameter: : isPassedByReference - Checks if passed by The reference ReflectionParameter: : isVariadic - Checks if the parameter is variadic ReflectionParameter: : __toString - To stringCopy the code
ReflectionMethod: 5.1: getParameters ()
As with the get method, this method returns an array containing a ReflectionParameter object for each parameter of the method
$method = new ReflectionMethod('Student', 'setName');
$params = $method->getParameters();
var_dump($params);Copy the code
Print the result
array (size=1)
0 => &
object(ReflectionParameter)[2]
public 'name' => string 'name' (length=4)Copy the code
5.2 ReflectionParameter
Let’s take a look at this approach. To better understand it, I’ll modify the setName method of the Student class by adding two arguments, a and b
. public function setName($name, $a, $b) { $this->name = $name; }...Copy the code
First let’s look at the constructor of the ReflectionParameter class
public ReflectionParameter::__construct ( string $function , string $parameter )Copy the code
You can see that the class receives two arguments when instantiated:
$function: If you want to get a function as a public function, just pass the function name. When the function is a class method, you pass an array of the form array(‘class’, ‘function’).
$parameter: This parameter can be passed in two ways, the first as the parameter name (without the $sign) and the second as the parameter index. Note: Either the parameter name or index must exist, otherwise an error will be reported.
Here’s an example:
$params = new ReflectionParameter(array('Student', 'setName'), 1);
var_dump($params);Copy the code
Print the result
object(ReflectionParameter)[1]
public 'name' => string 'a' (length=1)Copy the code
Let’s define another function to test it out
function foo($a, $b, $c) { }
$reflect = new ReflectionParameter('foo', 'c');
var_dump($reflect);Copy the code
Print the result
object(ReflectionParameter)[2]
public 'name' => string 'c' (length=1)Copy the code
6. Conclusion
PHP’s reflection API is a powerful tool for retrieving detailed information about a class. We can use the reflection API to write a class that dynamically calls the Module object, which is free to load third-party plug-ins and integrate them into existing systems. Without the need to hardcode third-party code into the original code. Although reflection is rarely used in actual development, understanding the reflection API can be very helpful in understanding code structure at work and developing business patterns. This blog post was written on and off for a long time (mainly lazy!). , if there are mistakes and deficiencies welcome to correct, suggestions!!