您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關什么是PHP反射API,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
PHP中的反射API就像Java中的java.lang.reflect包一樣。它由一系列可以分析屬性、方法和類的內置類組成。它在某些方面和對象函數相似,比如get_class_vars(),但是更加靈活,而且可以提供更多信息。
反射API也可與PHP最新的面向對象特性一起工作,如訪問控制、接口和抽象類。舊的類函數則不太容易與這些新特性一起使用。看過框架源碼的朋友應該對PHP的反射機制有一定的了解,像是依賴注入,對象池,類加載,一些設計模式等等,都用到了反射機制。
反射API的部分類
使用反射API這些類,可以獲得在運行時訪問對象、函數和腳本中的擴展的信息。通過這些信息可以用來分析類或者構建框架。
類 | 描 述 |
Reflection | 為類的摘要信息提供靜態函數export() |
ReflectionClass | 類信息和工具 |
ReflectionMethod | 類方法信息和工具 |
ReflectionParameter | 方法參數信息 |
ReflectionProperty | 類屬性信息 |
ReflectionFunction | 函數信息和工具 |
ReflectionExtension | PHP擴展信息 |
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反射API,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。