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);
}
}
......
}