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 — 判斷方法是否是建構方法
Reflection::isDestructor —Method判斷方法是否為析構方法
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!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

PHP仍然流行的原因是其易用性、靈活性和強大的生態系統。 1)易用性和簡單語法使其成為初學者的首選。 2)與web開發緊密結合,處理HTTP請求和數據庫交互出色。 3)龐大的生態系統提供了豐富的工具和庫。 4)活躍的社區和開源性質使其適應新需求和技術趨勢。

PHP和Python都是高層次的編程語言,廣泛應用於Web開發、數據處理和自動化任務。 1.PHP常用於構建動態網站和內容管理系統,而Python常用於構建Web框架和數據科學。 2.PHP使用echo輸出內容,Python使用print。 3.兩者都支持面向對象編程,但語法和關鍵字不同。 4.PHP支持弱類型轉換,Python則更嚴格。 5.PHP性能優化包括使用OPcache和異步編程,Python則使用cProfile和異步編程。

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

PHP在現代化進程中仍然重要,因為它支持大量網站和應用,並通過框架適應開發需求。 1.PHP7提升了性能並引入了新功能。 2.現代框架如Laravel、Symfony和CodeIgniter簡化開發,提高代碼質量。 3.性能優化和最佳實踐進一步提升應用效率。

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

Dreamweaver Mac版
視覺化網頁開發工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。