美文网首页我爱编程
PHP反射机制介绍

PHP反射机制介绍

作者: 祐吢房_2c9a | 来源:发表于2018-05-25 18:08 被阅读0次

Php Reflection API是PHP5才有的新功能,它是用来导出或提取关于类、方法、属性、参数等的详细信息,包括注释。

常用的就只有两个,ReflectionClass和ReflectionObject,前者针对类,后者针对对象,后者是继承前者的类;然后其中又有一些属性或方法能返回对应的reflection对象。

PHP反射机制,对类、接口、函数、方法和扩展进行反向工程的能力。

分析类、接口、函数和方法的内部结构,方法和函数的参数,以及类的属性和方法。

常用的几个类:

  • ReflectionClass解析类
  • ReflectionProperty类的属性的相关信息
  • ReflectionMethod类方法的有关信息
  • ReflectionParameter取回函数或方法参数的相关信息
  • ReflectionFunction 一个函数的相关信息

示例类

class Student
{
    public $id;
    
    public $name;

    const MAX_AGE = 200;

    public static $likes = [];

    public function __construct($id, $name = 'li')
    {
        $this->id = $id;
        $this->name = $name;
    }

    public function study()
    {
        echo 'learning...';
    }

    private function _foo()
    {
        echo 'foo';
    }

    protected function bar($to, $from = 'zh')
    {
        echo 'bar';
    }
}

ReflectionClass

//ReflectionClass
$ref = new ReflectionClass('student');

//判断类是否可实例化
if($ref->isInstantiable()){
    echo "可实例化";
}

//获取构造函数,有返回ReflectionMethod对象,没有返回null
$constructor = $ref->getConstructor();

//获取某个属性
if ($ref->hasProperty('id')) {
    $attr = $ref->getProperty('id');
}

//获取属性列表
$attributes = $ref->getProperties();
foreach ($attributes as $row){
    echo $row->getName()."\n";
}

//获取静态属性,返回数组
$static = $ref->getStaticProperties();

//获取某个常量
if ($ref->hasConstant('MAX_AGE')) {
    $const = $ref->getConstant('MAX_AGE');
}

//获取所有常量
$constants = $ref->getConstants();

//获取某个方法
if ($ref->hasMethod('bar')) {
    $method = $ref->getMethod('bar');
}

//获取方法列表
$methods = $ref->getMethods();

ReflectionProperty

if ($ref->hasProperty('name')) {
  $attr = $ref->getProperty('name');
  //属性名称
  echo $attr->getName();
  //类定义时属性为真,运行时添加的属性为假
  var_dump($attr->isDefault());
  //判断属性访问权限
  $attr->isPrivate();
  $attr->isPublic();
  $attr->isProtected();
  //判断属性是否为静态
  $attr->isStatic();
}

ReflectionMethod & ReflectionParameter

$method = $ref->getMethod('bar');
//对方法的判断
//isAbstruct()
//isConstructor()
//isDestructor()
//isFinal()
//isPrivate()
//isPublic()
//isProtected()
//isStatic()

//获取参数列表
$parameters = $method->getParameters();
foreach ($parameters as $row) {
    echo $row->getName();
    echo $row->getClass();
    
    //检查是否有默认值
    if ($row->isDefaultValueAvailable()) {
        echo $row->getDefaultValue();
    }
  
    //获取变量类型
    if ($row->hasType()) {
        echo $row->getType();
    }
}

ReflectionFunction & ReflectionParameter

$fun = new ReflectionFunction('demo');
echo $fun->getName();
$parameters = $fun->getParameters();
foreach ($parameters as $row) {
    // 这里的 $row 为 ReflectionParameter 实例
    echo $row->getName();
    echo $row->getClass();

    // 检查变量是否有默认值
    if ($row->isDefaultValueAvailable()) {
        echo $row->getDefaultValue();
    }

    // 获取变量类型
    if ($row->hasType()) {
        echo $row->getType();
    }
}

综合实例

使用反射实例化类

//student.php
class Student
{
    public $id;
    
    public $name;

    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }

    public function study()
    {
        echo 'learning.....';
    }

}

一般情况下,实例化类的时候可以直接new,但是我们现在不用这种方法,我们使用反射来实现。

//index.php
require 'student.php';
function make($class, $vars = [])
{
    $ref = new ReflectionClass($class);
  
    if ($ref->isInstantiable()) {
        $constructor = $ref->getConstructor();
        if (is_null($constructor)) {
            return new $class;
        }
      
        //获取构造函数参数
        $params = $constructor->getParameters();
        $resolveParams = [];
        foreach ($params as $key => $param) {
            $name = $param->getName();
            if (isset($vars[$name])) {
                //判断如果是传递的参数,直接使用传递参数
                $resolveParams[] = $vars[$name];
            } else {
                //没有传递参数的话,检查是否有默认值,没有默认值的话,按照类名进行递归解析
                $default = $param->isDefaultValueAvailable() ? $param->isDefaultValueAvailable() : null;
                if (is_null($default)) {
                    if ($param->getClass()) {
                        $resolveParams[] = make($value->getClass()->name, $vars);
                    } else {
                        throw new Exception("{$name}没有传值且没有默认值");
                    }
                } else {
                     $resolveParams[] = $default;
                }
            }
        }
        //根据参数实例化
        return $ref->newInstanceArgs($resolveParams);
    } else {
        throw new Exception("类 {$class} 不存在");
    }
}

情况一

try {
    $stu = make('Student', ['id' => 1, 'name'=>'li']);
    print_r($stu);
    $stu->study();
} catch(Exception $e) {
    echo $e->getMessage();
}

情况二

try {
    $stu = make('Student', ['id' => 1, 'name'=>'li', 'study'=> new Study]);
    print_r($stu);
    $stu->study();
} catch(Exception $e) {
    echo $e->getMessage();
}

那么这种情况下,在分析类的构造函数参数的时候,如果没有传递参数的话,就会递归调用 make 方法处理 Study 类,如果类存在的话,实例化。
PHP 的反射是一个很用的功能,我这里只能很简单的讲解了一点皮毛,详细介绍和用法可参看 官方手册

相关文章

  • PHP反射机制介绍

    Php Reflection API是PHP5才有的新功能,它是用来导出或提取关于类、方法、属性、参数等的详细信息...

  • PHP Reflection 反射

    反射 ReflectionClass 类 PHP反射机制 反射在 PHP 中的应用

  • PHP 反射机制

    php官方在线手册: http://php.net/manual/zh/book.reflection.php 反...

  • PHP反射机制

    反射-官网地址 这里创建一个测试类 返回结果: 返回结果: 返回结果: 加我微信公众号【皮蛋馅儿】,一起学习哦~

  • Java反射机制详解(一)

    接下来我们将介绍Java反射机制的一系列的知识。本篇文章主要针对Java反射机制的介绍以及反射API的使用知识。 ...

  • PHP反射机制Reflection

    反射机制简介 在面向对象编程中,对象被系统赋予了自省的能力,而实现这个自省的过程就是反射。 ​反射,简单理解就是根...

  • Java反射机制学习总结

    介绍反射机制 1.反射机制的应用场景 逆向代码、动态生成类框架等,使用反射机制能够大大的增强程序的扩展性。 2.反...

  • JAVA反射机制介绍

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的...

  • golang反射机制介绍

    golang反射机制介绍 Go语言提供了一种机制,在编译时不知道类型的情况下,可更新变量、在运行时查看值、调用方法...

  • java反射机制

    ## 3.2 反射 ## ### 3.2.1 反射介绍 ### JAVA反射机制是在运行状态中,对于任意一个类,都...

网友评论

    本文标题:PHP反射机制介绍

    本文链接:https://www.haomeiwen.com/subject/llmujftx.html