Heim  >  Artikel  >  Backend-Entwicklung  >  Erfahren Sie mehr über die PHP Reflection API!

Erfahren Sie mehr über die PHP Reflection API!

青灯夜游
青灯夜游nach vorne
2020-07-24 17:01:341879Durchsuche

Erfahren Sie mehr über die PHP Reflection API!

Die Reflection-API in PHP ähnelt dem java.lang.reflect-Paket in Java. Es besteht aus einer Reihe integrierter Klassen, die Eigenschaften, Methoden und Klassen analysieren können. Es ähnelt in mancher Hinsicht Objektfunktionen, wie z. B. get_class_vars(), ist jedoch flexibler und kann mehr Informationen bereitstellen.

Die Reflection API funktioniert auch mit den neuesten objektorientierten Funktionen von PHP, wie Zugriffskontrolle, Schnittstellen und abstrakten Klassen. Ältere Klassenfunktionen sind mit diesen neuen Funktionen weniger einfach zu verwenden. Freunde, die den Quellcode des Frameworks gelesen haben, sollten ein gewisses Verständnis für den Reflexionsmechanismus von PHP haben, z. B. Abhängigkeitsinjektion, Objektpooling, Klassenladen, einige Entwurfsmuster usw., die alle Reflexionsmechanismen verwenden.

Einige Klassen der Reflection-API

Mit diesen Klassen der Reflection-API können Sie Laufzeitzugriff auf Objekte, Funktionen und Erweiterungen erhalten Informationen zu Skripten. Diese Informationen können zum Analysieren von Klassen oder zum Erstellen von Frameworks verwendet werden.

Informationen und Tools zur Klassenmethode
描         述
Reflection 为类的摘要信息提供静态函数export()
ReflectionClass 类信息和工具
ReflectionMethod 类方法信息和工具
ReflectionParameter 方法参数信息
ReflectionProperty 类属性信息
ReflectionFunction 函数信息和工具
ReflectionExtension PHP扩展信息
ReflectionException 错误类
Klasse
Beschreibung
Reflection Stellt zusammenfassende Informationen für die Klasse Static bereit function export()
ReflectionClass Klasseninformationen und Tools
ReflectionMethod
ReflectionParameter Informationen zu Methodenparametern
ReflectionProperty td > Informationen zu Klassenattributen
ReflectionFunction Funktionsinformationen und Tools
ReflectionExtension / td> PHP-Erweiterungsinformationen
ReflectionException Fehlerklasse

Klasseninformationen abrufen

Wir haben in unserer Arbeit einige Funktionen zum Überprüfen von Klassenattributen verwendet, wie zum Beispiel: get_class_methods, getProduct usw. Diese Methoden weisen erhebliche Einschränkungen beim Erhalten detaillierter Klasseninformationen auf.

Wir können relevante Informationen über die Klasse durch den von der Reflection-API-Klasse bereitgestellten statischen Methodenexport erhalten: Reflection und ReflectionClass-Export können fast alle Informationen über die Klasse bereitstellen, einschließlich des Zugriffskontrollstatus von Attributen und Methoden. und jede Methode. Die erforderlichen Parameter und die Position jeder Methode im Skriptdokument. Für diese beiden Werkzeugklassen sind die Ausgabeergebnisse der statischen Exportmethode gleich, die Verwendungsmethoden sind jedoch unterschiedlich.

Erstellen Sie zunächst eine einfache Klasse

<?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;
    }
}

Verwenden Sie ReflectionClass::export(), um Klasseninformationen abzurufen

ReflectionClass::export(&#39;Student&#39;);

Ergebnisse drucken:

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 ]
            }
        }
    }
}

Die ReflectionClass-Klasse bietet viele Werkzeugmethoden. Das offizielle Handbuch enthält die folgende Liste:

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&#39;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 对象字符串的表示形式。

Verwenden Sie Reflection::export(). um Klasseninformationen zu erhalten

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

Ergebnisse drucken

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 ]
            }
        }
    }
}

Nach dem Erstellen des ReflectionClass-Objekts können Sie die Reflection-Toolklasse verwenden, um Informationen über die Student-Klasse auszugeben. Reflection::export() kann Instanzen jeder Klasse formatieren und exportieren, die die Reflector-Schnittstelle implementiert.

Klasse prüfen

Wir haben bereits früher von der ReflectionClass-Werkzeugklasse erfahren und wissen, dass diese Klasse viele Werkzeugmethoden zum Erhalten von Klassen bereitstellt Information. Zum Beispiel können wir den Typ der Student-Klasse abrufen und ob sie instanziiert werden kann

Werkzeugfunktion

function classData(ReflectionClass $class) {
    $details = &#39;&#39;;
    $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(&#39;Student&#39;);
print classData($prodClass);

Ergebnisse drucken

Student is user defined
Student can be instantiated

Zusätzlich zum Abrufen der relevanten Informationen der Mit der Klasse können Sie auch die ReflectionClass-Objekte abrufen, die relevante Quellcodeinformationen bereitstellen, z. B. den Dateinamen, in dem sich die benutzerdefinierte Klasse befindet, sowie die Start- und Endzeilen der Klasse in der Datei.

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(&#39;Student&#39;);
var_dump(getClassSource($prodClass));

Ergebnisse drucken

string &#39;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;
    }
}
&#39; (length=486)

Wir sehen, dass getClassSource ein ReflectionClass-Objekt als Parameter akzeptiert und den Quellcode der entsprechenden Klasse zurückgibt. Diese Funktion ignoriert die Fehlerbehandlung, in der Praxis sollten die Parameter und der Ergebniscode überprüft werden!

Überprüfen von Methoden

Ähnlich wie beim Überprüfen von Klassen können ReflectionMethod-Objekte zum Überprüfen von Methoden in einer Klasse verwendet werden.

Es gibt zwei Möglichkeiten, ReflectionMethod-Objekte abzurufen:

Die erste besteht darin, ein Array von ReflectionMethod-Objekten über ReflectionClass::getMethods() abzurufen Sie müssen den Methodennamen im Voraus kennen. Gibt ReflectionMethod-Objekte für alle Methoden in der Klasse zurück.

Die zweite Methode besteht darin, die ReflectionMethod-Klasse direkt zum Instanziieren des Objekts zu verwenden. Diese Methode kann nur ein Klassenmethodenobjekt abrufen, und Sie müssen den Methodennamen im Voraus kennen.

Dienstprogrammmethoden von ReflectionMethod-Objekten:

ReflectionMethod::__construct – Konstruktor von ReflectionMethod
ReflectionMethod::export – Exportiert eine Rückrufmethode
ReflectionMethod::getClosure – Gibt zurück Eine dynamisch erstellte Methodenaufrufschnittstelle. Hinweis des Übersetzers: Sie können diesen Rückgabewert verwenden, um nicht öffentliche Methoden direkt aufzurufen.
ReflectionMethod::getDeclaringClass – Ruft die Klassendarstellung der Aufrufparameter der Reflektionsfunktion ab
ReflectionMethod::getModifiers – Ruft die Modifikatoren der Methode ab
ReflectionMethod::getPrototype – Gibt den Methodenprototyp zurück (falls vorhanden)
ReflectionMethod::invoke – Aufrufen
ReflectionMethod::invokeArgs – Mit Parametern ausführen
ReflectionMethod::isAbstract – Bestimmen, ob die Methode eine abstrakte Methode ist
ReflectionMethod::isConstructor – Bestimmen, ob die Methode ein Konstruktor ist
ReflectionMethod::isDestructor – Bestimmen Sie, ob die Methode eine Destruktormethode ist
ReflectionMethod::isFinal – Bestimmen Sie, ob die Methode endgültig definiert ist
ReflectionMethod::isPrivate – Bestimmen Sie, ob die Methode eine private Methode ist
ReflectionMethod ::isProtected — Bestimmt, ob die Methode eine geschützte Methode (protected) ist
ReflectionMethod::isPublic — Bestimmt, ob die Methode eine öffentliche Methode ist
ReflectionMethod::isStatic — Bestimmt, ob die Methode eine statische Methode ist
ReflectionMethod::setAccessible – Legt fest, ob auf die Methode zugegriffen werden kann
ReflectionMethod::__toString – Gibt den Zeichenfolgenausdruck des Reflexionsmethodenobjekts zurück

ReflectionClass::getMethods()

Wir können es über das ReflectionClass::getMethods() Array von ReflectionMethod-Objekten erhalten.

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

Ergebnisse drucken

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

Sie können sehen, dass wir das Objektarray „Student’s ReflectionMethod“ erhalten haben. Jedes Element ist ein Objekt, das zwei öffentliche Attribute hat: Name ist der Methodenname und Klasse ist Kategorie . Wir können Objektmethoden aufrufen, um Methodeninformationen zu erhalten.

ReflectionMethod

Verwenden Sie direkt die ReflectionMethod-Klasse, um Informationen über Klassenmethoden zu erhalten

$method = new ReflectionMethod(&#39;Student&#39;, &#39;setName&#39;);
var_dump($method);

Ergebnisse drucken

object(ReflectionMethod)[1]
  public &#39;name&#39; => string &#39;setName&#39; (length=7)
  public &#39;class&#39; => string &#39;Student&#39; (length=7)

Achtung

在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&#39;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&#39;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(&#39;Student&#39;, &#39;setName&#39;);
$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(&#39;Student&#39;, &#39;setName&#39;), 1);
var_dump($params);

打印结果

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

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

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

打印结果

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

结语

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

相关教程推荐:《PHP教程

Das obige ist der detaillierte Inhalt vonErfahren Sie mehr über die PHP Reflection API!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen