php 赵亚飞_PHP反射API

近期忙着写项目,没有学习什么特别新的东西,所以好长时间没有更新博客。我们的项目用的是lumen,是基于laravel的一个轻量级框架,我看到里面用到了一些反射API机制来帮助动态加载需要的类、判断方法等,所以本篇文章就把在PHP中经常用到的反射API给大家分享一下吧,想学习反射API的同学可以看看。

说起反射ApI,自我感觉PHP中的反射ApI和java中的java.lang.reflect包差不多,都是由可以打印和分析类成员属性、方法的一组内置类组成的。可能你已经学习过对象函数比如:get_class_vars()但是使用反射API会更加的灵活、输出信息会更加详细。

首先我们需要知道,反射API不仅仅是用来检查类的,它本身包括一组类,用来完成各种功能:常用的类如下:

Reflection类

可以打印类的基本信息,(通过提供的静态export()函数)

ReflectionMethod类

见名知意,打印类方法、得到方法的具体信息等

ReflectionClass类

用于得到类信息,比如得到类包含的方法,类本的属性,是不是抽象类等

ReflectionParameter类

显示参数的信息,可以动态得到已知方法的传参情况

ReflectionException类

用于显示错误信息

ReflectionExtension类

得到PHP的扩展信息,可以判断扩展是否存在等

传统的打印类信息与反射APi的区别

下面是一段我自己写的参数程序,用于演示反射的使用:

1 <?php2

3 classPerson4 {5 //成员属性

6 public $name;7 public $age;8

9 //构造方法

10 public function __construct($name, $age)11 {12 $this->name = $name;13 $this->age = $age;14 }15

16 //成员方法

17 public function set_name($name)18 {19 $this->$name = $name;20 }21

22 public functionget_name()23 {24 return $this->$name;25 }26

27 public functionget_age()28 {29 return $this->$age;30 }31

32 public functionget_user_info()33 {34 $info = '姓名:' . $this->name;35 $info .= ' 年龄:' . $this->age;36 return $info;37 }38 }39

40 class Teacher extendsPerson41 {42 private $salary = 0;43

44 public function __construct($name, $age, $salary)45 {46 parent::__construct($name, $age);47 $this->salary = $salary;48 }49

50 public functionget_salary()51 {52 return $this->$salary;53 }54

55 public functionget_user_info()56 {57 $info = parent::get_user_info();58 $info .= " 工资:" . $this->salary;59 return $info;60 }61 }62

63 class Student extendsPerson64 {65 private $score = 0;66

67 public function __construct($name, $age, $score)68 {69 parent::__construct($name, $age);70 $this->score = $score;71 }72

73 public functionget_score()74 {75 return $this->score;76 }77

78 public functionget_user_info()79 {80 $info = parent::get_user_info();81 $info .= " 成绩:" . $this->score;82 return $info;83 }84 }85

86 header("Content-type:text/html;charset=utf8;");87 $te_obj = new Teacher('李老师', '36', '2000');88 $te_info = $te_obj->get_user_info();89

90 $st_obj = new Student('小明', '13', '80');91 $st_info = $st_obj->get_user_info();

我们先用var_dump();打印类的信息,如下所示,可以看出只是打印出类的简单信息,甚至连方法也没有,所以从这样的信息中看不出其他游泳的信息。

var_dump($te_obj);

1 object(Teacher)#1 (3) {

2 ["salary":"Teacher":private]=>

3 string(4) "2000"

4 ["name"]=>

5 string(9) "李老师"

6 ["age"]=>

7 string(2) "36"

8 }

Reflection::export($obj);

我们利用Reflection提供的内置方法export来打印信息,如下所示:

打印出的信息比较完整,包括成员属性,成员方法,类的基本信息,文件路径,方法信息,方法属性,传参情况,所在文件的行数等等。比较全面的展示了类的信息。可以看出var_dump()或者print_r只能显示类的简要信息,好多信息根本显示不出来,所以他们只能做简单的调试之用,反射Api则提供的类更多的信息,可以很好地帮助我们知道调用类的情况,这对写接口,特别是调用别人的接口提供了极大的便利。如果出了问题,也可以帮助调试。

1 object(Teacher)#1 (3) {

2 ["salary":"Teacher":private]=>

3 string(4) "2000"

4 ["name"]=>

5 string(9) "李老师"

6 ["age"]=>

7 string(2) "36"

8 }9 Class [ classPerson ] {10 @@ /usr/local/www/phptest/oop/reflaction.php 3-38

11 - Constants [0] {12 }13 - Static properties [0] {14 }15 - Static methods [0] {16 }17 - Properties [2] {18 Property [ public $name]19 Property [ public $age]20 }21

22 - Methods [5] {23 Method [ publicmethod __construct ] {24 @@ /usr/local/www/phptest/oop/reflaction.php 10 - 14

25

26 - Parameters [2] {27 Parameter #0 [ $name ]

.....

反射API的具体使用:

看过框架源码的同学都知道框架都可以加载第三方的插件、类库等等。下面这个例子咱们借助反射APi简单实现这个功能,该例子原型是我从书上学习的,我理解后按照自己的思路写了一套:要实现的功能:用一个类去动态的遍历调用Property类对象,类可以自由的加载其他的类的方法,而不用吧类嵌入到已有的代码,也不用手动去调用类库的代码。

约定:每一个类要包含work方法,可以抽象出一个接口。可以把每个类的信息放在文件中,相当于各个类库信息,通过类保存的Property类库的对应对象,然后调用每个类库的work方法。

下面是基础代码:

1 /*属性接口*/

2 interfaceProperty3 {4 functionwork();5 }6

7 classPerson8 {9 public $name;10 public function __construct($name)11 {12 $this->name = $name;13 }14 }15

16 class StudentController implementsProperty17 {18 //set方法,但需要Person对象参数

19 public function setPerson(Person $obj_person)20 {21 echo 'Student ' . $obj_person->name;22 }23

24 //work方法简单实现

25 public functionwork()26 {27 echo 'student working!';28 }29 }30

31 class EngineController implementsProperty32 {33 //set方法

34 public function setWeight($weight)35 {36 echo 'this is engine -> set weight';37 }38

39 public function setPrice($price)40 {41 echo "this is engine -> set price";42 }43

44 //work方法简单实现

45 public functionwork()46 {47 echo 'engine working!';48 }49 }

这里定义了两个相似类实现Property接口,同时都简单实现work()方法 StudentController类稍微不同,参数需要Person对象,同时我们可以使用文件来保存各个类的信息,我们也可以用成员属性代替。

1 classRun2 {3 public static $mod_arr =[];4 public static $config =[5 'StudentController' =>[6 'person' => 'xiao ming'

7 ],

8 'EngineController' =>[9 'weight' => '500kg',

10 'price' => '4000'

11 ]12 ];13

14 //加载初始化

15 public function__construct()16 {17 $config = self::$config;18 //用于检查是不是实现类

19 $property = new ReflectionClass('Property');20 foreach ($config as $class_name => $params) {21 $class_reflect = new ReflectionClass($class_name);22 if(!$class_reflect->isSubclassOf($property)) {//用isSubclassOf方法检查是否是这个对象

23 echo 'this is error';24 continue;25 }26

27 //得到类的信息

28 $class_obj = $class_reflect->newInstance();29 $class_method = $class_reflect->getMethods();30

31 foreach ($class_method as $method_name) {32 $this->handle_method($class_obj, $method_name, $params);33 }34 array_push(self::$mod_arr, $class_obj);35 }36 }37

38 //处理方法调用

39 public function handle_method(Property $class_obj, ReflectionMethod $method_name, $params)40 {41 $m_name = $method_name->getName();42 $args = $method_name->getParameters();43

44 if(count($args) != 1 || substr($m_name, 0, 3) != 'set') {45 return false;46 }47 //大小写转换,做容错处理

48 $property = strtolower(substr($m_name, 3));49

50 if(!isset($params[$property])) {51 return false;52 }53

54 $args_class = $args[0]->getClass();55 echo '

';56         if(empty($args_class)) {57             $method_name->invoke($class_obj, $params[$property]); //如果得到的类为空证明需要传递基础类型参数

58 } else{59 $method_name->invoke($class_obj, $args_class->newInstance($params[$property])); //如果不为空说明需要传递真实对象

60 }61 }62 }63

64 //程序开始

65 new Run();

到此程序结束,Run启动会自动调用构造方法,初始化要加载类库的其他成员属性,包括初始化和执行相应方法操作,这里只是完成了对应的set方法。其中$mod_arr属性保存了所有调用类的对象,每个对象包含数据,可以遍历包含的对象来以此调用work()方法。

程序只做辅助理解反射PAI用,各个功能没有完善,里面用到了好多反射API的类,方法,下面会有各个方法的总结。

反射API提供的常用类和函数:

下面提供的函数是常用的函数,不是全部,有的函数根本用不到,所以我们有往撒谎那个写,想看全部的可以到网上搜一下,比较多。提供的这组方法没有必要背下来,用到的时候可以查看。

1 1:Reflection2   public static export(Reflector r [,bool return])//打印类或方法的详细信息

3   public static getModifierNames(int modifiers) //取得修饰符的名字

4

5 2:ReflectionMethod:6 public static string export() //打印该方法的信息

7 public mixed invoke(stdclass object, mixed* args) //调用对应的方法

8 public mixed invokeArgs(stdclass object, array args)//调用对应的方法,传多参数

9 public bool isFinal() //方法是否为final

10 public bool isAbstract() //方法是否为abstract

11 public bool isPublic()  //方法是否为public

12 public bool isPrivate()  //方法是否为private

13 public bool isProtected()  //方法是否为protected

14 public bool isStatic()  //方法是否为static

15 public bool isConstructor()  //方法是否为构造函数

17

18 3:ReflectionClass:19 public static string export() //打印类的详细信息

20 public string getName() //取得类名或接口名

21 public bool isInternal()  //类是否为系统内部类

22 public bool isUserDefined()   //类是否为用户自定义类

23 public bool isInstantiable() //类是否被实例化过

24 public bool hasMethod(string name) //类是否有特定的方法

25 public bool hasProperty(string name)//类是否有特定的属性

26 public string getFileName() //获取定义该类的文件名,包括路径名

27 public int getStartLine() //获取定义该类的开始行

28 public int getEndLine() //获取定义该类的结束行

29 public string getDocComment() //获取该类的注释

30 public ReflectionMethod getConstructor()           //取得该类的构造函数信息

31 public ReflectionMethod getMethod(string name) //取得该类的某个特定的方法信息

32 public ReflectionMethod[] getMethods()  //取得该类的所有的方法信息

33 public ReflectionProperty getProperty(string name) //取得某个特定的属性信息

34 public ReflectionProperty[] getProperties() //取得该类的所有属性信息

35 public array getConstants() //取得该类所有常量信息

36 public mixed getConstant(string name) //取得该类特定常量信息

37 public ReflectionClass[] getInterfaces() //取得接口类信息

38 public bool isInterface() //测试该类是否为接口

39 public bool isAbstract() //测试该类是否为抽象类

40

41 4:ReflectionParameter:42 public static string export()   //导出该参数的详细信息

43 public string getName()     //取得参数名

44 public bool isPassedByReference() //测试该参数是否通过引用传递参数

45 public ReflectionClass getClass() //若该参数为对象,返回该对象的类名

46 public bool isArray()  //测试该参数是否为数组类型

47 public bool allowsNull()  //测试该参数是否允许为空

48 public bool isOptional() //测试该参数是否为可选的,当有默认参数时可选

49 public bool isDefaultValueAvailable() //测试该参数是否为默认参数

50 public mixed getDefaultValue() //取得该参数的默认值

51

52 5:ReflectionExtension类

54 public static export() //导出该扩展的所有信息

55 public string getName() //取得该扩展的名字

56 public string getVersion() //取得该扩展的版本

57 public ReflectionFunction[] getFunctions() //取得该扩展的所有函数

58 public array getConstants() //取得该扩展的所有常量

59 public array getINIEntries() //取得与该扩展相关的,在php.ini中的指令信息

60 }

写的比较急,难免会有错误,还请大神们多多指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水利改革发展 中国政府高度重视水利建设,将水利作为国家基础设施建设的优先领域。政策文件强调了防洪抗旱、水资源管理、水环境保护和水生态修复等方面的全面要求,推动了水利信息化的发展。 智慧水利建设目标 智慧水利的建设目标是通过数据共享、应用惠民、应急预警等手段,打破信息孤岛,提升应急抢险协作能力,加强水利数据在惠民信息化方面的应用。同时,提出了共享联动化、解决信息安全问题、提高水利信息科技创新能力等目标。 智慧水利建设模式 智慧水利的建设模式包括构建统一平台、数据中心、信息整合平台、决策支持系统等,以实现水利、海洋、环保等政府部门和公众的信息共享和服务。此外,还包括了云计算虚拟化、网络传输、采集工程等多个方面的技术应用。 智慧水利应用实例 智慧水利的应用实例包括视频水文工程监控、多要素一体化检测设备、汛情预警智能联动、三防决策指挥、河长综合信息展示等。这些应用通过集成GIS、互联网地图服务、物联网设备等技术,实现了对水利设施的实时监控、数据分析和应急响应。 成功案例与展望 智慧水利的成功案例展示了通过视频监控、预警信息发布、移动办公信息APP等技术,有效提升了灾害应对能力、水资源管理和河长制的实施效果。这些案例表明,智慧水利的建设不仅提高了水利管理的效率和水平,也为未来的水利信息化发展提供了方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值