27
07月
2020
常用的反射类
类名 | 作用 |
---|---|
Reflection | 可以打印类的基本信息,(通过提供的静态export()函数) |
ReflectionMethod | 见名知意,打印类方法、得到方法的具体信息等 |
ReflectionClass | 用于得到类信息,比如得到类包含的方法,类本的属性,是不是抽象类等 |
ReflectionParameter | 显示参数的信息,可以动态得到已知方法的传参情况 |
ReflectionException | 用于显示错误信息 |
ReflectionExtension | 得到PHP的扩展信息,可以判断扩展是否存在等 |
extend/A.php
<?php /** * Class A */ class A { public $a; private $b; public function __construct($a, $b) { $this->a = $a; $this->b = $b; } /** * A类的abc方法 * * @param $a * @param $b * * @return string */ public function abc($a, $b) { return "abcd"; } /** * type方法 * * @param int $type * * @return string */ public function type($type = 1) { return "type:" . $type; } }
application/index/controller/Index.php
反射类和获取属性
//$obj = new \A("a", 'b'); //$refClass = new \ReflectionClass($obj); //或者 $refClass = new \ReflectionClass("A"); // 将类名作为参数,建立反射类 //var_dump($refClass); /** * 打印 * object(ReflectionClass)#34 (1) * { * ["name"]=> string(1) "A" * } */ $properties = $refClass->getProperties(); // 所有属性 //var_dump($properties); /** * 打印 * array(2) * { * [0]=> object(ReflectionProperty)#35 (2) * { * ["name"]=> string(1) "a" * ["class"]=> string(1) "A" * } * [1]=> object(ReflectionProperty)#36 (2) * { * ["name"]=> string(1) "b" * ["class"]=> string(1) "A" * } * } */ $property = $refClass->getProperty('a'); //var_dump($property); /** * 打印 * object(ReflectionProperty)#37 (2) * { * ["name"]=> string(1) "a" * ["class"]=> string(1) "A" * } */
反射方法
$methods = $refClass->getMethods(); // 获取类的所有方法 //var_dump($methods); /** * 打印 * array(3) * { * [0]=> object(ReflectionMethod)#38 (2) * { * ["name"]=> string(11) "__construct" * ["class"]=> string(1) "A" * } * [1]=> object(ReflectionMethod)#39 (2) * { * ["name"]=> string(3) "abc" * ["class"]=> string(1) "A" * } * [2]=> object(ReflectionMethod)#40 (2) * { * ["name"]=> string(2) "mf" * ["class"]=> string(1) "A" * } * } */ $method = $refClass->getMethod("abc"); //var_dump($method); /** * 打印 * object(ReflectionMethod)#41 (2) * { * ["name"]=> string(3) "abc" * ["class"]=> string(1) "A" * } */
反射注释
$document = $refClass->getDocComment(); // 获取类定义在类之前的注释 //var_dump($document); // 打印 // string(18) "/** * Class A */" $document = $refClass->getMethod('abc')->getDocComment(); //var_dump($document); // 打印 // string(105) "/** * A类的abc方法 * * @param $a * @param $b * * @return string */"
反射实例化新类
$newInstance = $refClass->newInstance("a", "b"); // 从指定的参数创建一个新的类实例 //var_dump($newInstance); /** * 打印 * object(A)#42 (2) * { * ["a"]=> string(1) "a" * ["b":"A":private]=> string(1) "b" * } */ $params = ['a', "b"]; $newInstance = $refClass->newInstanceArgs($params); // 从给出的参数创建一个新的类实例 //var_dump($newInstance); /** * 打印 * object(A)#42 (2) * { * ["a"]=> string(1) "a" * ["b":"A":private]=> string(1) "b" * } */
反射实例化新类可访问、执行类的公有方法
$ret = $newInstance->type(1); // 调用类的实例调用type方法 //var_dump($ret); // 打印 // string(6) "type:1" $refClass->getProperty('a')->setValue($newInstance, 'a'); // 设置属性值 $a = $refClass->getProperty('a')->getValue($newInstance); // 获取属性值 //var_dump($a); // 打印 // string(1) "a" $ret = $refClass->getMethod('type')->invoke($newInstance, '2'); // 调用类的实例调用type方法 //var_dump($ret); // 打印 // string(6) "type:2"
判断某个方法是否公用的
$method = new \ReflectionMethod('A', 'abc'); var_dump($method->isPublic()); // 打印 // bool(true)
THINKPHP 源码中的使用
thinkphp/library/think/Container.php
class Container implements ArrayAccess, IteratorAggregate, Countable { ...... /** * 调用反射执行类的方法 支持参数绑定 * @access public * @param mixed $method 方法 * @param array $vars 参数 * @return mixed */ public function invokeMethod($method, $vars = []) { try { if (is_array($method)) { $class = is_object($method[0]) ? $method[0] : $this->invokeClass($method[0]); $reflect = new ReflectionMethod($class, $method[1]); } else { // 静态方法 $reflect = new ReflectionMethod($method); } $args = $this->bindParams($reflect, $vars); return $reflect->invokeArgs(isset($class) ? $class : null, $args); } catch (ReflectionException $e) { if (is_array($method) && is_object($method[0])) { $method[0] = get_class($method[0]); } throw new Exception('method not exists: ' . (is_array($method) ? $method[0] . '::' . $method[1] : $method) . '()'); } } ...... /** * 调用反射执行类的实例化 支持依赖注入 * @access public * @param string $class 类名 * @param array $vars 参数 * @return mixed */ public function invokeClass($class, $vars = []) { try { $reflect = new ReflectionClass($class); if ($reflect->hasMethod('__make')) { $method = new ReflectionMethod($class, '__make'); if ($method->isPublic() && $method->isStatic()) { $args = $this->bindParams($method, $vars); return $method->invokeArgs(null, $args); } } $constructor = $reflect->getConstructor(); $args = $constructor ? $this->bindParams($constructor, $vars) : []; return $reflect->newInstanceArgs($args); } catch (ReflectionException $e) { throw new ClassNotFoundException('class not exists: ' . $class, $class); } } ...... }