PHP反射机制原理与用法
2018-01-12 00:00
525 查看
反射
反射,直观理解就是根据到达地找到出发地和来源。比如,一个光秃秃的对象,我们可以仅仅通过这个对象就能知道它所属的类、拥有哪些方法。反射是指在PHP运行状态中,扩展分析PHP程序,导出或提出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取信息以及动态调用对象方法的功能称为反射API。
php类的成员变量没有在类中声明,而是在函数中声明,有什么不同?
ReflectionClass:获取类声明时的结构ReflectionObject:可获取类实例化后的结构
代码如下:
class test{
private $name;
private $sex;
function __construct(){
$this->aaa='aaa';
}
}
$test=new test();
$reflect=new ReflectionClass($test);
$pro=$reflect->getDefaultProperties();
print_r($pro);//打印结果:Array ( [name] =>[sex] =>)
echo $test->aaa;//打印结果:aaa
在这个test类中,声明了两个成员变量$name和$sex,但是在构造函数中,又声明了一个变量$aaa,初始化类,使用反射类打印默认成员属性只有声明的两个成员变量属性,但是打印类的$aaa变量发现还是可以输出结果。
请问类的成员变量不用声明,在函数中声明也是可以的吗,有什么区别?
在你这个例子中,使用ReflectionClass是不恰当的,因为__construct只有在实例化class时,才会执行。
也就是说ReflectionClass更多的是反射类声明时的结构,而不是类实例化后的结构,所以没有输出属性aaa是正确,因为属性aaa确实是(在类声明时)不存在的。
那么怎么看属性aaa呢,应该用ReflectionObject反射实例化后的结构,例如
代码如下:
<?php
class test{
private $name;
private $sex;
function __construct(){
$this->aaa='aaa';
}
}
$test=new test();
$reflect=new ReflectionObject($test);
$pro=$reflect->getProperties();
print_r($pro);
经过实例化以后,属性aaa才会存在,这时你就能看到属性aaa了
如何使用反射API
例子:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php class person{ public $name ; public $gender ; public function say(){ echo $this ->name, " \tis " , $this ->gender, "\r\n" ; } public function set( $name , $value ) { echo "Setting $name to $value \r\n" ; $this -> $name = $value ; } public function get( $name ) { if (!isset( $this -> $name )){ echo '未设置' ; $this -> $name = "正在为你设置默认值" ; } return $this -> $name ; } } $student = new person(); $student ->name= 'Tom' ; $student ->gender= 'male' ; $student ->age=24; |
1 2 3 4 5 6 7 8 9 10 11 | // 获取对象属性列表 $reflect = new ReflectionObject( $student ); $props = $reflect ->getProperties(); foreach ( $props as $prop ) { $prop ->getName() . "\n" ; } // 获取对象方法列表 $m = $reflect ->getMethods(); foreach ( $m as $prop ) { $prop ->getName() . "\n" ; } |
1 2 3 4 5 6 | // 返回对象属性的关联数组 var_dump(get_object_vars( $student )); // 类属性 var_dump(get_class_vars(get_class( $student ))); // 返回由类的方法名组成的数组 var_dump(get_class_methods(get_class( $student ))); |
1 2 | // 获取对象属性列表所属的类 echo get_class( $student ); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // 反射获取类的原型 $obj = new ReflectionClass( 'person' ); $className = $obj ->getName(); $Methods = $Properties = array (); foreach ( $obj ->getProperties() as $v ){ $Properties [ $v ->getName()] = $v ; } foreach ( $obj ->getMethods() as $v ) { $Methods [ $v ->getName()] = $v ; } echo "class {$className}\n{\n" ; is_array ( $Properties )&&ksort( $Properties ); foreach ( $Properties as $k => $v ){ echo "\t" ; echo $v ->isPublic() ? ' public' : '' , $v ->isPrivate() ? ' private' : '' , $v ->isProtected() ? ' protected' : '' , $v ->isStatic() ? ' static' : '' ; echo "\t{$k}\n" ; } echo "\n" ; if ( is_array ( $Methods )) ksort( $Methods ); foreach ( $Methods as $k => $v ){ echo "\tfunction {$k}(){}\n" ; } echo "}\n" ; |
1 2 3 4 5 6 7 8 | class person { public gender public name function get(){} function set(){} function say(){} } |
反射有什么作用
反射可以用于文档生成。因此可以用它对文件里的类进行扫描,逐个生成描述文档。既然反射可以探知类的内部结构,那么是不是可以用它做hook实现插件功能呢?或者是做动态代理呢?
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?php class mysql { function connect( $db ) { echo "连接到数据库${db[0]}\r\n" ; } } class sqlproxy { private $target ; function construct( $tar ) { $this ->target[] = new $tar (); } function call( $name , $args ) { foreach ( $this ->target as $obj ) { $r = new ReflectionClass( $obj ); if ( $method = $r ->getMethod( $name )) { if ( $method ->isPublic() && ! $method ->isAbstract()) { echo "方法前拦截记录LOG\r\n" ; $method ->invoke( $obj , $args ); echo "方法后拦截\r\n" ; } } } } } $obj = new sqlproxy( 'mysql' ); $obj ->connect( 'member' ); |
PHP有Token函数,可以通过这个机制实现一些反射功能。从简单灵活的角度讲,使用已经提供的反射API是可取的。
很多时候,善用反射能保持代码的优雅和简洁,但反射也会破坏类的封装性,因为反射可以使本不应该暴露的方法或属性被强制暴露了出来,这既是优点也是缺点。
相关文章推荐
- PHP反射机制原理与用法详解
- PHP反射机制原理与用法详解
- PHP面向对象自动加载机制原理与用法分析
- PHP面向对象自动加载机制原理与用法分析
- PHP反射机制用法实例
- PHP反射机制用法实例
- PHP 底层的运行机制与原理
- 跟着辛星用PHP的反射机制来实现插件
- PHP 反射机制实现动态代理的代码
- PHP 底层的运行机制与原理解析
- 理解php反射机制-2
- JAVA 反射机制,invoke调用用法一个小的用法
- PHP的运行机制与原理(底层)
- PHP中的插件机制原理和实例
- 番外 01:Spring IoC 实现原理简析,Java的反射机制,通过类名创建对象
- PHP的反射机制
- java原理—反射机制
- 浏览器三种刷新方式的缓存机制-----单点登录SSO的实现原理---PHP版单点登陆实现方案
- qt 信号,槽及反射机制的实现原理 (记录 gui programing with qt 4)
- PHP实现依赖注入-使用反射机制和动态代理技术 - 简单思想(咋个办呢 zgbn)