分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

PHP中的反射

发布时间:2023-09-06 02:25责任编辑:蔡小小关键词:PHP

  面向对象编辑中对象被赋予了自省的能力,而这个自省的过程就是反射.

  反射,直观理解应时根据到达地找出出发地和来源.比方说,我给你一个光秃秃的对象,我可以仅仅通过这个对象就能知道它所属的类,拥有哪些方法.
反射指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类,方法,属性,参数等详细信息,包括注释.这种动态获取信息以及动态调用对象方法的功能称为反射API

如何使用反射API

以下面代码为例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
classHandsonBoy
{
public$name=‘chenqionghe‘;
public$age= 18;
publicfunction__set($name,$value)
{
echo‘您正在设置私有属性‘.$name.‘<br >值为‘.$value.‘<br>‘;
$this->$name=$value;
}
publicfunction__get($name)
{
if(!isset($this->$name))
{
echo‘未设置‘.$name;
$this->$name="正在为你设置默认值".‘<br>‘;
}
return$this->$name;
}
}
$boy=newHandsonBoy();
echo$boy->name.‘<br />‘;
$boy->hair =‘short‘;
现在,要获取这个student对象的方法和属性列表该怎么做?可以用反射来实现,代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
$reflect=newReflectionObject($boy);
$props=$reflect->getProperties();
//获取属性的名字
foreach($propsas$prop)
{
print$prop->getName().PHP_EOL;
}
//获取对象方法列表
$methos=$reflect->getMethods();
foreach($methosas$method)
{
print$method->getName().PHP_EOL;
}

也可以不用反射API,使用class函数,返回对象属性的关联数组以及更多的信息:(针对于公开的属性和):

1
2
3
4
5
6
//返回对象属性的关联数组
var_dump(get_object_vars($boy));
//类属性
var_dump(get_class_vars(get_class($boy)));
//返回由类的属性的方法名组成的数组
var_dump(get_class_methods(get_class($boy)));

反射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
25
26
27
28
29
30
31
32
33
/**
* @param $classObject 对象或者类名
*/
functiongetClass($classObject)
{
$object=newReflectionClass($classObject);
$className=$object->getName();
$Methods=$Properties=array();
foreach($object->getProperties()as$v)
{
$Properties[$v->getName()] =$v;
}
foreach($object->getMethods()as$v)
{
$Methods[$v->getName()] =$v;
}
echo"class {$className}\n{\n";
is_array($Properties) && ksort($Properties);
foreach($Propertiesas$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($Methodsas$k=>$v)
{
echo"\tfunction {$k}()\n";
}
echo"}\n";
}

不仅如此,PHP手册中关于反射API更是有几十个,可以说,反射完整地描述了一个类或者对象的原型.反射不仅可以用于类和对象,还可以用于函数,扩展模块,异常等.

反射有什么作用

反射可以用于文档生成,因此可以用它对文件里的类进行扫描,逐个生成描述文档.
既然反射可以探知类内部结构, 那么是不是 可以用它做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
27
28
29
30
31
32
33
34
<?php
classmysql
{
functionconnect($db)
{
echo"连接到数据库{$db[0]}".PHP_EOL;
}
}
classsqlproxy
{
private$target;
publicfunction__construct($tar)
{
$this->target[] =new$tar;
}
publicfunction__call($name,$args)
{
foreach($this->targetas$obj)
{
$r=newReflectionClass($obj);
if($method=$r->getMethod($name))
{
if($method->isPublic() && !$method->isAbstract())
{
echo"方法前拦截记录LOG".PHP_EOL;
$method->invoke($obj,$args);
echo"方法后拦截".PHP_EOL;
}
}
}
}
}
$obj=newsqlproxy(‘mysql‘);
$obj->connect(‘chenqionghe‘);
  这里真正操作类是mysql类,但是sqlproxy实现了根据动态传入参数,代替实际的类运行,并且在方法运行前后进行拦截,并且动态地改变类中的方法和属性.这就是简单的动态代理.
  在平常的开发中用到反射的地方并不多: 一个是对对象进行调试,别一个是获取类的信息.在MVC和插件开发中,使用反射很常见,但是反射的消耗也很大,在可以找到替代方案的情况下,就不要滥用.
  PHP有Token函数,可以通过这个机制实现一些反射功能.从简单灵活的角度讲,使用已经提供的反射API是可取的.
  很多时候,善用反射能保持代码的优雅和简洁,但反射也会破坏类的封装性,因为反射可以使本不应该暴露的方法或属性被强制暴露了出来,这既是优点也是缺点.

PHP中的反射

原文地址:https://www.cnblogs.com/liliuguang/p/10062502.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved