Подробно объясните API рефлексии PHP.

PHP
API отражения в PHP похож на пакет java.lang.reflect в Java. Он состоит из ряда встроенных классов, которые могут анализировать свойства, методы и классы. В некоторых отношениях она похожа на объектные функции, такие как get_class_vars(), но более гибкая и может предоставить больше информации. API отражения также работает с последними объектно-ориентированными функциями PHP, такими как управление доступом, интерфейсы и абстрактные классы. Функции старых классов не так просто использовать с этими новыми возможностями. Друзья, которые читали исходный код фреймворка, должны иметь определенное представление о механизме отражения PHP, таком как внедрение зависимостей, пул объектов, загрузка классов, некоторые шаблоны проектирования и т. д., все используют механизм отражения.

1. Некоторые классы API отражения

своего рода описывать
Reflection Предоставьте статическую функцию export() для сводной информации о классе.
ReflectionClass Информация о классе и инструменты
ReflectionMethod Информация о методе класса и инструменты
ReflectionParameter Информация о параметрах метода
ReflectionProperty информация об атрибутах класса
ReflectionFunction Информация о функциях и инструменты
ReflectionExtension Информация о расширении PHP
ReflectionException класс ошибки

 

 

 

 

 

 

 

 

 

Используя API отражения этих классов, мы можем получить информацию о доступе к объектам, функциям и расширениям в скриптах во время выполнения. Мы можем использовать эту информацию для анализа классов или конструкций сборки.

2. Получить информацию о классе

В своей работе мы использовали некоторые функции для проверки атрибутов класса, такие как: get_class_methods, getProduct и т.д. Эти методы имеют существенные ограничения для получения подробной информации о классе.

Мы можем получить информацию, связанную с классом, через класс API отражения: экспорт статического метода, предоставляемый Reflection и ReflectionClass, Экспорт может предоставить почти всю информацию о классе, включая статус контроля доступа к свойствам и методам, параметры, необходимые для каждого метода, и параметры каждого метода Расположение метода в документе скрипта. Для этих двух классов инструментов выходные результаты статического метода экспорта одинаковы, но используются они по-разному.

Сначала создайте простой класс

 1 <?php
 2 
 3 class Student {
 4     public    $name;
 5     protected $age;
 6     private   $sex;
 7 
 8     public function __construct($name, $age, $sex)
 9     {
10         $this->setName($name);
11         $this->setAge($age);
12         $this->setSex($sex);
13     }
14 
15     public function setName($name)
16     {
17         $this->name = $name;
18     }
19 
20     protected function setAge($age)
21     {
22         $this->age = $age;
23     }
24 
25     private function setSex($sex)
26     {
27         $this->sex = $sex;
28     }
29 }

2.1 Используйте 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 :: Export () вывод

Класс RefluictionClass обеспечивает много инструментов и методов. Список, заданный официальным руководством, выглядит следующим образом:

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 对象字符串的表示形式。
ReflectionClass

2.2 Используйте 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 ]
            }
        }
    }
}
Вывод Reflection::export()

После создания объекта ReflectionClass вы можете использовать класс инструментов Reflection для вывода информации о классе Student. Reflection::export() может форматировать и экспортировать экземпляр любого класса, реализующего интерфейс Reflector.

3. Проверить класс

Из класса инструментов 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 и возвращает исходный код соответствующего класса. Эта функция игнорирует обработку ошибок, на практике следует проверять аргументы и коды результатов!

4. Метод проверки

Подобно проверке классов, объекты ReflectionMethod можно использовать для проверки методов в классах.

Есть два способа получить объект ReflectionMethod:

Первый — получить массив объектов ReflectionMethod через ReflectionClass::getMethods() Преимущество этого метода в том, что вам не нужно заранее знать имя метода, и вы вернете объекты 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 — 返回反射方法对象的字符串表达
ReflectionMethod

4.1 ReflectionClass::getMethods()

Мы можем получить массив объектов ReflectionMethod через ReflectionClass::getMethods().

$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's ReflectionMethod, каждый элемент которого представляет собой объект, который имеет два общедоступных свойства, name — это имя метода, а class — это класс, к которому он принадлежит. Мы можем вызывать методы объекта, чтобы получить информацию о методах.

4.2 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)

4.3 Внимание

В PHP5 ReflectionMethod::retursReference() не вернет true, если проверяемый метод возвращает только объект (даже если объект присваивается или передается по ссылке). ReflectionMethod::returnsReference() возвращает значение true, только если инструментированный метод был явно объявлен для возврата ссылки (с амперсандом перед именем метода).

5. Проверьте параметры метода

В PHP5 тип объекта в параметре может быть ограничен при объявлении метода класса, поэтому возникает необходимость проверки параметров метода.

Подобно проверке методов, объект ReflectionParameter можно использовать для проверки методов в классе.Этот объект может сообщить вам имя параметра, может ли переменная быть передана по ссылке, он также может дать вам подсказки типа параметра и является ли метод принимает null в качестве параметра.

Есть два способа получить объект ReflectionParameter, что очень похоже на получение объекта ReflectionMethod:

Первый — вернуть массив объектов ReflectionParameter с помощью метода ReflectionMethod::getParameters(), который может получить все объекты параметров метода.

Второй — напрямую использовать класс 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
ReflectionParameter

5.1 ReflectionMethod::getParameters()

Как и метод get, этот метод возвращает массив, содержащий объекты 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)

5.2 ReflectionParameter

Давайте посмотрим на этот метод.Для лучшего понимания я изменю метод setName класса Student и добавлю два параметра a, b

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

Во-первых, давайте взглянем на конструктор класса ReflectionParameter.

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

Вы можете видеть, что класс получает два параметра при создании экземпляра:

$функция: когда вам нужно получить функцию как общедоступную, вам нужно только передать имя функции. Когда функция является методом класса, вам нужно передать массив в формате: массив('класс', 'функция').

$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)

6. Заключение

API отражения PHP очень мощный, он может получить подробную информацию о классе. Мы можем использовать API отражения, чтобы написать класс для динамического вызова объекта модуля, который может свободно загружать сторонние плагины и интегрироваться в существующую систему. Нет необходимости жестко встраивать сторонний код в исходный код. Хотя отражение редко используется в реальной разработке, понимание API отражения очень полезно для понимания структуры кода и разработки бизнес-моделей в работе. Этот пост в блоге писался от случая к случаю в течение длительного времени (в основном лень!), если есть какие-либо ошибки или недостатки, пожалуйста, поправьте меня, предложения! !