说到这个实例,首先介绍下本人,我是一个php程序员,从事drupal开发2年多,可以说从实习开始就接触这个,至今没有换过,drupal给我的感觉是俩字“强大”,今天写一个views的字段,然后需要继承views的views_handler_field类,还要自己实现里面的一些方法,走一些自己的配置设置,查看这个类的时候,发现实在是太多信息了,并且做了好些继承,于是我就想要是能实现一个功能,传入一个类名,然后就能返回类的所有信息(包括,属性,方法,继承,接口,并且这些类所放置的文件位置,以及在该文件的多少行)在使用drupal中的dpm函数一打印(层级查询,这是一个插件名字叫【krumo】),我赛这想法太好了啊。。。。。越想越有兴趣实现他了,
接下来我就想这该怎么实现呢,后来突然想到了,前些日子看的php模式与面向对象一书中有一章节叫反射api的,对了就是它,接下来开始coding............................
由于好长时间没有写类了,因为drupal还是一个函数式编程的概念,所以这个类写的不是太好,好希望大家多多指教,一起成长,下面附上代码。
<?php /** * use * $pros = new RefTools('calssname', true, false); * dpm($pros->Cinfo()); print_r($pros->Cinfo()); */ class RefTools { public $p_num; public $classname; public $isgetpar; /** * [constructor 构造方法] * @param [type] $classname [类名] * @return [type] [null] */ public function __construct($classname, $isgetpar=true){ $this->classname = $classname; $this->p_num = 0; $this->isgetpar = $isgetpar; } /** * [cInfo description] * @return [type] [description] */ public function cInfo() { return $this->getClassMethod($this->classname); } /** * [getReflectionObj 获取反射对象] * @param [type] $classname [类名] * @return [type] [对象] */ public function getReflectionObj($classname){ //这里如果这样传参$this->classname,会导致执行时间太长而栈溢出,我的测试环境开启了xdebug,有xdebug.max_nesting_level=150 //限制,但是通过传递参数就不会有此原因,知道的人一起交流交流 return new ReflectionClass($classname); } /** * [getClassMethod 获取类方法] * @param [type] $classname [类名] * @param boolean $isgetpar [是否继续查询父类] * @return [type] [数组] */ public function getClassMethod($classname){ $arr = array(); //获取反射对象 $pre = $this->getReflectionObj($classname); //获取反射对象的方法 $methods = $pre->getMethods(); $arr['tostring'] = $pre->__toString(); $arr['classinfo'] = $this->getClassInfo($pre); $arr['Properties'] = $this->getPropertiesData($pre->getProperties()); foreach ($methods as $key => $method) { $arr['method'][$method->getName()]['info'] = $this->getMethodData($method); $arr['method'][$method->getName()]['body'] = $this->getMethodSource($method); } //是否获取父类 if( $this->isgetpar ){ $parclass = $pre->getParentClass(); if(is_object($parclass)){ $this->p_num++; $arr['parents'][$parclass->name] = $this->getClassMethod($parclass->name,true,false); } } $arr['parent_num'] = $this->p_num; return $arr; } /** * [getClassInfo 获取类信息] * @param [type] $pre [反射类对象] * @return [type] [description] */ public function getClassInfo($pre){ $arr = array(); $arr['path'] = $pre->getFileName(); $arr['line'] = 'start:'.$pre->getStartLine().'****end:'.$pre->getEndLine(); $arr['interface'] = $pre->getInterfaceNames(); return $arr; } /** * [getPropertiesDataa 获取属性信息] * @param [type] $properties [arr] * @return [type] [string] */ public function getPropertiesData( $properties ){ $arr = array(); foreach ($properties as $key => $pp) { $pname = $pp->getName(); $arr[$pname] = '****来自于 '.$pp->class.' 类****'; } return $arr; } /** * [getMethodData 获取类方法信息] * @param ReflectionMethod $method [方法对象] * @return [type] [string] */ public function getMethodData( ReflectionMethod $method ){ $details = ''; $name = $method->getName(); if ( $method->isUserDefined() ) { $details .= "****** 【 $name 】 ******* is user defined\n"; } if ( $method->isInternal() ) { $details .= "****** 【 $name 】 ******* is built-in\n"; } if ( $method->isAbstract() ) { $details .= "****** 【 $name 】 ******* is abstract\n"; } if ( $method->isPublic() ) { $details .= "****** 【 $name 】 ******* is public\n"; } if ( $method->isProtected() ) { $details .= "****** 【 $name 】 ******* is protected\n"; } if ( $method->isPrivate() ) { $details .= "****** 【 $name 】 ******* is private\n"; } if ( $method->isStatic() ) { $details .= "****** 【 $name 】 ******* is static\n"; } if ( $method->isFinal() ) { $details .= "****** 【 $name 】 ******* is final\n"; } if ( $method->isConstructor() ) { $details .= "****** 【 $name 】 ******* is constructor\n"; } if ( $method->returnsReference() ) { $details .= "****** 【 $name 】 ******* return a reference (as opposed to a value)\n"; } return $details; } /** * [getMethodSource 获取方法体] * @param ReflectionMethod $method [反射方法对象] * @return [type] [string] */ public function getMethodSource ( ReflectionMethod $method ) { $path = $method->getFileName(); $lines = @file( $path ); $from = $method->getStartLine(); $to = $method->getEndLine(); $len = $to-$from+1; return Implode( array_slice( $lines, $from-1, $len )); } }
在 getReflectionObj 这个方法里面大家可能已经注意到了,大家可是试试,有知道解决方案的交流下。。。。。
这是我本地的截图:看着还是挺给力的,要是大家也想实现这种效果,本地也弄一个krumo