分享web开发知识

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

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

PHP核心技术——反射

发布时间:2023-09-06 02:36责任编辑:董明明关键词:PHP

反射:

  • 反射指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取信息以及动态调用对象方法的功能称为反射API
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;//获取对象属性列表$reflect = new ReflectionObject($student);$props = $reflect -> getProperties();foreach ($props as $prop) { ???print $prop -> getName()."\n";}//获取对象方法列表$m = $reflect -> getMethods();foreach ($m as $prop) { ???print $prop -> getName()."\n";}//返回对象属性的关联数组var_dump(get_object_vars($student));//类属性var_dump(get_class_vars(get_class($student)));//返回由类的方法名组成的数组var_dump(get_class_methods(get_class($student)));//获取对象属性列表所属的类echo get_class($student);
  • 反射API的功能显然更强大,甚至能还原这个类的原型,包括方法的访问权限,代码如下
//反射获取类的原型$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";
  • 反射可以探知类的内部结构,可以用它做hook实现插件功能或者是做动态代理
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');
  • 真正的操作类是mysql类,但是sqlproxy类实现了根据动态传入参数,代替实际的类运行,并且在方法运行前后进行拦截,并且动态地改变类中的方法和属性。这就是简单的动态代理。

参考资料

  • [PHP核心技术与最佳实践]

PHP核心技术——反射

原文地址:https://www.cnblogs.com/geniusrun/p/10607736.html

知识推荐

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