百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>网页制作> 深入理解PHP反射API!
分享文章到:

深入理解PHP反射API!

发布时间:09/01 来源:未知 浏览: 关键词:

PHP中的反射API就像Java中的java.lang.reflect包一样。它由一系列可以剖析属性、办法和类的内置类组成。它在某些方面和对象函数类似,比方get_class_vars(),但是愈加灵敏,并且可以供给更多信息。

反射API也可与PHP最新的面向对象特性一起工作,如拜访操纵、接口和抽象类。旧的类函数则不太容易与这些新特性一起使用。看过框架源码的伴侣应当对PHP的反射机制有必然的理解,像是依靠注入,对象池,类加载,一些设计模式等等,都用到了反射机制。

反射API的部分类

使用反射API这些类,可以获得在运转时拜访对象、函数和足本中的扩展的信息。通过这些信息可以用来剖析类或者构建框架。

描 述
Reflection为类的摘要信息供给静态函数export()
ReflectionClass类信息和工具
ReflectionMethod类办法信息和工具
ReflectionParameter办法参数信息
ReflectionProperty类属性信息
ReflectionFunction函数信息和工具
ReflectionExtensionPHP扩展信息
ReflectionException错误类

猎取类的信息

我们在工作中使用过一些用于检查类属性的函数,例如:get_class_methods、getProduct等。这些办法对猎取具体类信息有很大的局限性。

我们可以通过反射API类:Reflection 和 ReflectionClass 供给的静态办法 export 来猎取类的相关信息, export 可以供给类的几乎所有的信息,包罗属性和办法的拜访操纵状态、每个办法需要的参数乃至每个办法在足本文档中的位置。这两个工具类, export 静态办法输出结果是一致的,只是使用方式不一样。

第一,构建一个简便的类

<?php

class Student {
    public    $name;
    protected $age;
    private   $sex;

    public function __construct($name, $age, $sex)
    {
        $this->setName($name);
        $this->setAge($age);
        $this->setSex($sex);
    }

    public function setName($name)
    {
       $this->name = $name;
    }

    protected function setAge($age)
    {
        $this->age = $age;
    }

    private function setSex($sex)
    {
        $this->sex = $sex;
    }
}

使用 ReflectionClass::export() 猎取类信息

ReflectionClass::export('Student');

打印结果:

Class [ class Student ] {
    @@ D:\wamp\www\test2.php 3-29
    - Constants [0] { }
    - Static properties [0] { }
    - Static methods [0] { }
    - Properties [3] {
        Property [ public $name ]
        Property [ protected $age ]
        Property [ private $sex ]
    }
    - Methods [4] {
        Method [ public method __construct ] {
            @@ D:\wamp\www\test2.php 8 - 13
            - Parameters [3] {
                Parameter #0 [ $name ]
                Parameter #1 [ $age ]
                Parameter #2 [ $sex ]
            }
        }
        Method [ public method setName ] {
            @@ D:\wamp\www\test2.php 15 - 18
            - Parameters [1] {
                Parameter #0 [ $name ]
            }
        }
        Method [ protected method setAge ] {
            @@ D:\wamp\www\test2.php 20 - 23
            - Parameters [1] {
                Parameter #0 [ $age ]
            }
        }
        Method [ private method setSex ] {
            @@ D:\wamp\www\test2.php 25 - 28
            - Parameters [1] {
                Parameter #0 [ $sex ]
            }
        }
    }
}

ReflectionClass类供给了非常多的工具办法,官方手册给的列表如下:

ReflectionClass::__construct — 初始化 ReflectionClass 类
ReflectionClass::export — 输出一个类
ReflectionClass::getConstant — 猎取定义过的一个常量
ReflectionClass::getConstants — 猎取一组常量
ReflectionClass::getConstructor — 猎取类的结构函数
ReflectionClass::getDefaultProperties — 猎取默许属性
ReflectionClass::getDocComment — 猎取文档注释
ReflectionClass::getEndLine — 猎取最后一行的行数
ReflectionClass::getExtension — 按照已定义的类猎取所在扩展的 ReflectionExtension 对象
ReflectionClass::getExtensionName — 猎取定义的类所在的扩展的名称
ReflectionClass::getFileName — 猎取定义类的文件名
ReflectionClass::getInterfaceNames — 猎取接口(interface)名称
ReflectionClass::getInterfaces — 猎取接口
ReflectionClass::getMethod — 猎取一个类办法的 ReflectionMethod。
ReflectionClass::getMethods — 猎取办法的数组
ReflectionClass::getModifiers — 猎取类的润饰符
ReflectionClass::getName — 猎取类名
ReflectionClass::getNamespaceName — 猎取命名空间的名称
ReflectionClass::getParentClass — 猎取父类
ReflectionClass::getProperties — 猎取一组属性
ReflectionClass::getProperty — 猎取类的一个属性的 ReflectionProperty
ReflectionClass::getReflectionConstant — Gets a ReflectionClassConstant for a class's constant
ReflectionClass::getReflectionConstants — Gets class constants
ReflectionClass::getShortName — 猎取短名
ReflectionClass::getStartLine — 猎取起始行号
ReflectionClass::getStaticProperties — 猎取静态(static)属性
ReflectionClass::getStaticPropertyValue — 猎取静态(static)属性的值
ReflectionClass::getTraitAliases — 返回 trait 别号的一个数组
ReflectionClass::getTraitNames — 返回这个类所使用 traits 的名称的数组
ReflectionClass::getTraits — 返回这个类所使用的 traits 数组
ReflectionClass::hasConstant — 检查常量可否已经定义
ReflectionClass::hasMethod — 检查办法可否已定义
ReflectionClass::hasProperty — 检查属性可否已定义
ReflectionClass::implementsInterface — 接口的实现
ReflectionClass::inNamespace — 检查可否位于命名空间中
ReflectionClass::isAbstract — 检查类可否是抽象类(abstract)
ReflectionClass::isAnonymous — 检查类可否是匿名类
ReflectionClass::isCloneable — 返回了一个类可否可复制
ReflectionClass::isFinal — 检查类可否声明为 final
ReflectionClass::isInstance — 检查类的实例
ReflectionClass::isInstantiable — 检查类可否可实例化
ReflectionClass::isInterface — 检查类可否是一个接口(interface)
ReflectionClass::isInternal — 检查类可否由扩展或中心在内部定义
ReflectionClass::isIterateable — 检查可否可迭代(iterateable)
ReflectionClass::isSubclassOf — 检查可否为一个子类
ReflectionClass::isTrait — 返回了可否为一个 trait
ReflectionClass::isUserDefined — 检查可否由会员定义的
ReflectionClass::newInstance — 从指定的参数创立一个新的类实例
ReflectionClass::newInstanceArgs — 从给出的参数创立一个新的类实例。
ReflectionClass::newInstanceWithoutConstructor — 创立一个新的类实例而不调取它的结构函数
ReflectionClass::setStaticPropertyValue — 设定静态属性的值
ReflectionClass::__toString — 返回 ReflectionClass 对象字符串的表示情势。

使用 Reflection::export() 猎取类信息

$prodClass = new ReflectionClass('Student');
Reflection::export($prodClass);

打印结果

Class [ class Student ] {
    @@ D:\wamp\www\test2.php 3-29
    - Constants [0] { }
    - Static properties [0] { }
    - Static methods [0] { }
    - Properties [3] {
        Property [ public $name ]
        Property [ protected $age ]
        Property [ private $sex ]
    }
    - Methods [4] {
        Method [ public method __construct ] {
            @@ D:\wamp\www\test2.php 8 - 13
            - Parameters [3] {
                Parameter #0 [ $name ]
                Parameter #1 [ $age ]
                Parameter #2 [ $sex ]
            }
        }
        Method [ public method setName ] {
            @@ D:\wamp\www\test2.php 15 - 18
            - Parameters [1] {
                Parameter #0 [ $name ]
            }
        }
        Method [ protected method setAge ] {
            @@ D:\wamp\www\test2.php 20 - 23
            - Parameters [1] {
                Parameter #0 [ $age ]
            }
        }
        Method [ private method setSex ] {
            @@ D:\wamp\www\test2.php 25 - 28
            - Parameters [1] {
                Parameter #0 [ $sex ]
            }
        }
    }
}

创立 ReflectionClass对象后,就可以使用 Reflection 工具类输出 Student 类的相关信息。Reflection::export() 可以格局化和输出任何实现 Reflector 接口的类的实例。

检查类

前面我们理解的 ReflectionClass 工具类,知道此类供给了许多的工具办法用于猎取类的信息。例如,我们可以猎取到 Student 类的类型,可否可以实例化

工具函数

function classData(ReflectionClass $class) {
    $details = '';
    $name = $class->getName();          // 返回要检查的类名
    if ($class->isUserDefined()) {      // 检查类可否由会员定义
        $details .= "$name is user defined" . PHP_EOL;
    }
    if ($class->isInternal()) {         // 检查类可否由扩展或中心在内部定义
        $details .= "$name is built-in" . PHP_EOL;
    }
    if ($class->isInterface()) {        // 检查类可否是一个接口
        $details .= "$name is interface" . PHP_EOL;
    }
    if ($class->isAbstract()) {         // 检查类可否是抽象类
        $details .= "$name is an abstract class" . PHP_EOL;
    }
    if ($class->isFinal()) {            // 检查类可否声明为 final
        $details .= "$name is a final class" . PHP_EOL;
    }
    if ($class->isInstantiable()) {     // 检查类可否可实例化
        $details .= "$name can be instantiated" . PHP_EOL;
    } else {
        $details .= "$name can not be instantiated" . PHP_EOL;
    }
    return $details;
}

$prodClass = new ReflectionClass('Student');
print classData($prodClass);

打印结果

Student is user defined
Student can be instantiated

除了猎取类的相关信息,还可以猎取 ReflectionClass 对象供给自定义类所在的文件名及文件中类的起始和终止行等相关源代码信息。

function getClassSource(ReflectionClass $class) {
    $path  = $class->getFileName();  // 猎取类文件的绝对途径
    $lines = @file($path);           // 获得由文件中所有行组成的数组
    $from  = $class->getStartLine(); // 供给类的起始行
    $to    = $class->getEndLine();   // 供给类的终止行
    $len   = $to - $from + 1;
    return implode(array_slice($lines, $from - 1, $len));
}

$prodClass = new ReflectionClass('Student');
var_dump(getClassSource($prodClass));

打印结果

string 'class Student {
    public    $name;
    protected $age;
    private   $sex;

    public function __construct($name, $age, $sex)
    {
        $this->setName($name);
        $this->setAge($age);
        $this->setSex($sex);
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    protected function setAge($age)
    {
        $this->age = $age;
    }

    private function setSex($sex)
    {
        $this->sex = $sex;
    }
}
' (length=486)

我们看到 getClassSource 接受一个 ReflectionClass 对象作为它的参数,并返回响应类的源代码。该函数忽略了错误处置,在实际中应当要检查参数和结果代码!

检查办法

相似于检查类,ReflectionMethod 对象可以用于检查类中的办法。

获得 ReflectionMethod 对象的办法有两种:

第一种是通过 ReflectionClass::getMethods() 获得 ReflectionMethod 对象的数组,这种方式的好处是不消提早知道办法名,会返回类中所有办法的 ReflectionMethod 对象。

第二种是直接使用 ReflectionMethod 类实例化对象,这种方式只能猎取一个类办法对象,需要提早知道办法名。

ReflectionMethod 对象的工具办法:

ReflectionMethod::__construct — ReflectionMethod 的结构函数
ReflectionMethod::export — 输出一个回调办法
ReflectionMethod::getClosure — 返回一个动态创立的办法调取接口,译者注:可以使用这个返回值直接调取非公示办法。
ReflectionMethod::getDeclaringClass — 猎取反射函数调取参数的类表达
ReflectionMethod::getModifiers — 猎取办法的润饰符
ReflectionMethod::getPrototype — 返回办法原型 (假如存在)
ReflectionMethod::invoke — Invoke
ReflectionMethod::invokeArgs — 带参数施行
ReflectionMethod::isAbstract — 推断办法可否是抽象办法
ReflectionMethod::isConstructor — 推断办法可否是结构办法
ReflectionMethod::isDestructor — 推断办法可否是析构办法
ReflectionMethod::isFinal — 推断办法可否定义 final
ReflectionMethod::isPrivate — 推断办法可否是私有办法
ReflectionMethod::isProtected — 推断办法可否是庇护办法 (protected)
ReflectionMethod::isPublic — 推断办法可否是公示办法
ReflectionMethod::isStatic — 推断办法可否是静态办法
ReflectionMethod::setAccessible — 设定办法可否拜访
ReflectionMethod::__toString — 返回反射办法对象的字符串表达

ReflectionClass::getMethods()

我们可以通过 ReflectionClass::getMethods() 获得 ReflectionMethod 对象的数组。

$prodClass = new ReflectionClass('Student');
$methods = $prodClass->getMethods();
var_dump($methods);

打印结果

array (size=4)
  0 => &
    object(ReflectionMethod)[2]
      public 'name' => string '__construct' (length=11)
      public 'class' => string 'Student' (length=7)
  1 => &
    object(ReflectionMethod)[3]
      public 'name' => string 'setName' (length=7)
      public 'class' => string 'Student' (length=7)
  2 => &
    object(ReflectionMethod)[4]
      public 'name' => string 'setAge' (length=6)
      public 'class' => string 'Student' (length=7)
  3 => &
    object(ReflectionMethod)[5]
      public 'name' => string 'setSex' (length=6)
      public 'class' => string 'Student' (length=7)

可以看到我们猎取到了 Student 的 ReflectionMethod 对象数组,每个元素是一个对象,其中有两个公共的属性,name 为办法名,class 为所属类。我们可以调取对象办法来猎取办法的信息。

ReflectionMethod

直接使用 ReflectionMethod 类猎取类办法有关信息

$method = new ReflectionMethod('Student', 'setName');
var_dump($method);

打印结果

object(ReflectionMethod)[1]
  public 'name' => string 'setName' (length=7)
  public 'class' => string 'Student' (length=7)

留意

在PHP5中,假如被检查的办法只返回对象(即便对象是通过援用赋值或传递的),那么 ReflectionMethod::retursReference() 不会返回 true。只要当被检测的办法已经被明白声明返回援用(在办法名前面有&符号)时,ReflectionMethod::returnsReference() 才返回 true。

检查办法参数

在PHP5中,声明类办法时可以限制参数中对象的类型,因此检查办法的参数变得非常必要。

相似于检查办法,ReflectionParameter 对象可以用于检查类中的办法,该对象可以告诉你参数的名称,变量可否可以按援用传递,还可以告诉你参数类型提醒和办法可否接受空值作为参数。

获得 ReflectionParameter 对象的办法有一样两种,这和猎取 ReflectionMethod 对象非常相似:

第一种是通过 ReflectionMethod::getParameters() 办法返回 ReflectionParameter 对象数组,这种办法可以猎取到一个办法的全部参数对象。

第二种是直接使用 ReflectionParameter 类实例化猎取对象,这种办法只能猎取到简单参数的对象。

ReflectionParameter 对象的工具办法:

ReflectionParameter::allowsNull — Checks if null is allowed
ReflectionParameter::canBePassedByValue — Returns whether this parameter can be passed by value
ReflectionParameter::__clone — Clone
ReflectionParameter::__construct — Construct
ReflectionParameter::export — Exports
ReflectionParameter::getClass — Get the type hinted class
ReflectionParameter::getDeclaringClass — Gets declaring class
ReflectionParameter::getDeclaringFunction — Gets declaring function
ReflectionParameter::getDefaultValue — Gets default parameter value
ReflectionParameter::getDefaultValueConstantName — Returns the default value's constant name if default value is constant or null
ReflectionParameter::getName — Gets parameter name
ReflectionParameter::getPosition — Gets parameter position
ReflectionParameter::getType — Gets a parameter's type
ReflectionParameter::hasType — Checks if parameter has a type
ReflectionParameter::isArray — Checks if parameter expects an array
ReflectionParameter::isCallable — Returns whether parameter MUST be callable
ReflectionParameter::isDefaultValueAvailable — Checks if a default value is available
ReflectionParameter::isDefaultValueConstant — Returns whether the default value of this parameter is constant
ReflectionParameter::isOptional — Checks if optional
ReflectionParameter::isPassedByReference — Checks if passed by reference
ReflectionParameter::isVariadic — Checks if the parameter is variadic
ReflectionParameter::__toString — To string

ReflectionMethod::getParameters()

同猎取办法,此办法会返回一个数组,包括办法每个参数的 ReflectionParameter 对象

$method = new ReflectionMethod('Student', 'setName');
$params = $method->getParameters();
var_dump($params);

打印结果

array (size=1)
  0 => &
    object(ReflectionParameter)[2]
      public 'name' => string 'name' (length=4)

ReflectionParameter

我们来理解一下这种方式,为了更好的懂得,我修改一下 Student 类的 setName办法,增添两个参数 a, b

...
    public function setName($name, $a, $b)
    {
        $this->name = $name;
    }
...

第一我们看一下 ReflectionParameter 类的结构办法

public ReflectionParameter::__construct ( string $function , string $parameter )

可以看到该类实例化时接收两个参数:

$function:当需要猎取函数为公共函数时只需传函数名称即可。当该函数是某个类办法时,需要传递一个数组,格局为:array('class', 'function')。

$parameter:这个参数可以传递两种,第一种为参数名(无$符号),第二种为参数索引。留意:不管是参数名还是索引,该参数都必需存在,不然会报错。

下面举例:

$params = new ReflectionParameter(array('Student', 'setName'), 1);
var_dump($params);

打印结果

object(ReflectionParameter)[1]
  public 'name' => string 'a' (length=1)

我们再定义一个函数测试一下

function foo($a, $b, $c) { }
$reflect = new ReflectionParameter('foo', 'c');
var_dump($reflect);

打印结果

object(ReflectionParameter)[2]
  public 'name' => string 'c' (length=1)

结语

php的反射API功效非常的强大,它可以将一个类的具体信息猎取出来。我们可以通过反射API编写个类来动态调取Module对象,该类可以自在加载第三方插件并集成进已有的系统。而不需要把第三方的代码硬编码进原有的代码中。虽然实际开发中使用反射状况比力少,但理解反射API对工作中对代码构造的理解和开发业务模式帮忙还是非常大的。此篇博文东拉西扯的写了很久(主要就是懒!),如有错误与不足欢迎指正,倡议!!

相关教程引荐:《PHP教程》

以上就是深入理解PHP反射API!的具体内容,更多请关注百分百源码网其它相关文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有150人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板