我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

反射既然能分析函数,也就能黑盒分析代码中的类。在本文中,苏南大叔就来对系统类和一个自定义类进行一下黑盒分析。看看在php8ReflectionClass是个什么样的效果。

苏南大叔:未知php代码分析,如何利用reflection反射分析类class? - reflection-class
未知php代码分析,如何利用reflection反射分析类class?(图5-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码经验文章。本文测试环境:win10nginx@1.15.11php@8.2.10-nts。本文的代码部分使用了php8中的最新特性的写法。如果您运行的时候报错,请检查是否使用的是php8系列,或者改写一下代码也可以。

类定义和实体对象

在本文中,必须清晰的界定反射代码所操作的对象。是类的定义,还是被实例化后的对象?
例如,在下面的代码中:

$obj = new ClassA("abc");

这里$obj就是实例对象,ClassA就是类的定义。它们之间至少差着一个参数abc,它们两个并不是一个东西。所以,在向本文中的各种函数中,传递要分析的对象的时候,请想清楚自己传递的到底是类,还是实例。

获得公有变量

直接使用get_class_vars()就可以获得这个类的所有公开属性。(拿不到私有属性的,不要费力气了)

var_dump(get_class_vars("ClassA"));

获得公有方法

直接使用get_class_methods()就可以获得这个类的所有公开方法。(拿不到私有方法的,不要费力气了)

var_dump(get_class_methods("ClassA"));

苏南大叔:未知php代码分析,如何利用reflection反射分析类class? - 黑盒分析变量和方法
未知php代码分析,如何利用reflection反射分析类class?(图5-2)

反射ReflectionClass 可以获得的信息

现在假设对类ClassA进行分析:

$r = new ReflectionClass("ClassA");
$constants = $r->getConstants();
获得内容使用方法
类常量$r->getConstants()
类默认属性$r->getDefaultProperties()
文件名$r->getFileName()
类定义开始行$r->getStartLine()
类定义结束行$r->getEndLine()
类定义注释$r->getDocComment()
其它.....

这里并不是全部信息,只是苏南大叔认为可能比较常用的。更多可用方法可以参考:

苏南大叔:未知php代码分析,如何利用reflection反射分析类class? - 可能有用的反射方法
未知php代码分析,如何利用reflection反射分析类class?(图5-3)

获得实例变量

前面已经说过了,实例和类定义是不一样的。类定义是模版,只可以被实例化。而实例是注入了灵魂,是可以操作的对象。那么,这里可以使用get_object_vars()获得实例变量的可用属性。

var_dump(get_object_vars($obj));

类的实例化,并不会影响类方法。所以,这里并不存在get_object_methods()的类似函数,可以直接去分析对应的类。比如:

var_dump(get_object_vars(get_class($obj)));

实例代码分析对象

本文打算利用ReflectionClass对如下两个类进行分析:
1、ReflectionClass自身进行分析。
2、自定义类SuNan进行分析。

分析调用代码:

function analyze($class_name){

    echo "\nget_class_vars():\n";
    print_r(get_class_vars($class_name));

    echo "\nget_class_methods():\n";
    print_r(get_class_methods($class_name));

    //#####################################
    $r = new ReflectionClass($class_name);
    echo "\ngetConstants():\n";
    print_r($r->getConstants());

    echo "\ngetDefaultProperties():\n";
    print_r($r->getDefaultProperties());

    echo "\ngetFileName():\n";
    print_r($r->getFileName());

    echo "\ngetStartLine():\n";
    print_r($r->getStartLine());

    echo "\ngetEndLine():\n";
    print_r($r->getEndLine());

    echo "\ngetDocComment():\n";
    print_r($r->getDocComment());
    //#####################################

    echo "\nget_object_vars():\n";
    print_r(get_object_vars($r));
}

分析ReflectionClass

analyze("ReflectionClass");

结果输出:

get_class_vars():
Array
(
    [name] => 
)

get_class_methods():
Array
(
    [0] => __construct
    [1] => __toString
    [2] => getName
    [3] => isInternal
    [4] => isUserDefined
    [5] => isAnonymous
    [6] => isInstantiable
    [7] => isCloneable
    [8] => getFileName
    [9] => getStartLine
    [10] => getEndLine
    [11] => getDocComment
    [12] => getConstructor
    [13] => hasMethod
    [14] => getMethod
    [15] => getMethods
    [16] => hasProperty
    [17] => getProperty
    [18] => getProperties
    [19] => hasConstant
    [20] => getConstants
    [21] => getReflectionConstants
    [22] => getConstant
    [23] => getReflectionConstant
    [24] => getInterfaces
    [25] => getInterfaceNames
    [26] => isInterface
    [27] => getTraits
    [28] => getTraitNames
    [29] => getTraitAliases
    [30] => isTrait
    [31] => isEnum
    [32] => isAbstract
    [33] => isFinal
    [34] => isReadOnly
    [35] => getModifiers
    [36] => isInstance
    [37] => newInstance
    [38] => newInstanceWithoutConstructor
    [39] => newInstanceArgs
    [40] => getParentClass
    [41] => isSubclassOf
    [42] => getStaticProperties
    [43] => getStaticPropertyValue
    [44] => setStaticPropertyValue
    [45] => getDefaultProperties
    [46] => isIterable
    [47] => isIterateable
    [48] => implementsInterface
    [49] => getExtension
    [50] => getExtensionName
    [51] => inNamespace
    [52] => getNamespaceName
    [53] => getShortName
    [54] => getAttributes
)

getConstants():
Array
(
    [IS_IMPLICIT_ABSTRACT] => 16
    [IS_EXPLICIT_ABSTRACT] => 64
    [IS_FINAL] => 32
    [IS_READONLY] => 65536
)

getDefaultProperties():
Array
(
)

getFileName():

getStartLine():

getEndLine():

getDocComment():

get_object_vars():
Array
(
    [name] => ReflectionClass
)

分析自定义类

自定义类的定义如下:

/**
 * 类定义的注释信息
 */
class SuNan{
    var $city = "北京";  //analyze
    const FROM = "北京朝阳";
    public $name = "苏南大叔";
    public int $age = 18;
    private bool $rich = true;
    public function __construct(public string $www,private string $domain){
        
    }
    public function getWww(){
        return $this->www."=>".$this->getDomain();
    }
    private function getDomain(){
        return $this->domain;
    }
}

分析自定义类SuNan

analyze("SuNan");

结果输出:

get_class_vars():
Array
(
    [city] => 北京
    [name] => 苏南大叔
    [age] => 18
    [www] => 
)

get_class_methods():
Array
(
    [0] => __construct
    [1] => getWww
)

getConstants():
Array
(
    [FROM] => 北京朝阳
)

getDefaultProperties():
Array
(
    [city] => 北京
    [name] => 苏南大叔
    [age] => 18
    [rich] => 1
)

getFileName():
C:\Users\sunan\Desktop\test\php\test.php
getStartLine():
6
getEndLine():
21
getDocComment():
/**
 * 类定义的注释信息
 */
get_object_vars():
Array
(
    [name] => SuNan
)

苏南大叔:未知php代码分析,如何利用reflection反射分析类class? - 分析自定义类
未知php代码分析,如何利用reflection反射分析类class?(图5-4)

再次对比class_varsobject_vars

$sn = new SuNan("程序如此灵动", "newsn.net");
print_r(get_class_vars("SuNan"));
print_r(get_object_vars($sn));

输出:

Array
(
    [city] => 北京
    [name] => 苏南大叔
    [age] => 18
    [www] => 
)
Array
(
    [city] => 北京
    [name] => 苏南大叔
    [age] => 18
    [www] => 程序如此灵动
)

苏南大叔:未知php代码分析,如何利用reflection反射分析类class? - 再次对比分析
未知php代码分析,如何利用reflection反射分析类class?(图5-5)

相关文档

结束语

本文主要是讲述对php的类做黑盒分析的方式和方法。更多的php相关经验文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php