核心要點
class_exists()
、get_class()
、get_parent_class()
和 is_subclass_of()
。這些函數提供有關類的基本信息,例如它們的名稱、父類的名稱等等。 ReflectionClass
類是 API 的主要類,用於對類、接口和方法應用反射。 PHP 內省機制是任何編程語言中的一種常見特性,它允許程序員操作對像類。當您在設計時不知道需要執行哪個類或方法時,您會發現內省特別有用。 PHP 中的內省提供了檢查類、接口、屬性和方法的有用功能。 PHP 提供大量可用於完成此任務的函數。為了幫助您理解內省,我將使用 PHP 中的示例簡要概述一些 PHP 的類、方法和函數,以突出它們的使用方式。在本文中,您將看到一些關於如何使用一些最有用的 PHP 內省函數的示例,以及一個專門介紹提供類似於內省功能的 API(反射 API)的部分。
PHP 內省函數
在第一個示例中,我將演示一些 PHP 的內省函數。您可以使用這些函數來提取有關類的基本信息,例如它們的名稱、父類的名稱等等。
class_exists()
– 檢查是否已定義類get_class()
– 返回對象的類名get_parent_class()
– 返回對象的父類的類名is_subclass_of()
– 檢查對像是否具有給定的父類以下是包含 Introspection
和 Child
類定義的示例 PHP 代碼,以及上面列出的函數提取的信息輸出:
<code class="language-php"><?php class Introspection { public function description() { echo "I am a super class for the Child class.\n"; } } class Child extends Introspection { public function description() { echo "I'm " . get_class($this) , " class.\n"; echo "I'm " . get_parent_class($this) , "'s child.\n"; } } if (class_exists("Introspection")) { $introspection = new Introspection(); echo "The class name is: " . get_class($introspection) . "\n"; $introspection->description(); } if (class_exists("Child")) { $child = new Child(); $child->description(); if (is_subclass_of($child, "Introspection")) { echo "Yes, " . get_class($child) . " is a subclass of Introspection.\n"; } else { echo "No, " . get_class($child) . " is not a subclass of Introspection.\n"; } } ?></code>
上述代碼的輸出應如下所示:
<code class="language-php"><?php class Introspection { public function description() { echo "I am a super class for the Child class.\n"; } } class Child extends Introspection { public function description() { echo "I'm " . get_class($this) , " class.\n"; echo "I'm " . get_parent_class($this) , "'s child.\n"; } } if (class_exists("Introspection")) { $introspection = new Introspection(); echo "The class name is: " . get_class($introspection) . "\n"; $introspection->description(); } if (class_exists("Child")) { $child = new Child(); $child->description(); if (is_subclass_of($child, "Introspection")) { echo "Yes, " . get_class($child) . " is a subclass of Introspection.\n"; } else { echo "No, " . get_class($child) . " is not a subclass of Introspection.\n"; } } ?></code>
您可以使用 class_exists()
方法確定是否已定義給定的類,該方法採用表示要檢查的所需類的名稱的字符串參數,以及一個可選的布爾值,指示是否在過程中調用自動加載器。 get_class()
和 get_parent_class()
方法分別返回對象的類名或其父類的類名。兩者都將對象實例作為參數。 is_subclass_of()
方法將對象實例作為其第一個參數,並將表示父類名的字符串作為第二個參數,並返回對像是否屬於作為參數給出的類的子類。
以下是一個第二個示例,其中包含 ICurrencyConverter
接口和 GBPCurrencyConverter
類的定義,以及上面列出的函數提取的信息輸出。與第一個示例一樣,我將首先列出函數,然後向您展示一些代碼。
get_declared_classes()
– 返回所有已聲明類的列表get_class_methods()
– 返回類方法的名稱get_class_vars()
– 返回類的默認屬性interface_exists()
– 檢查接口是否已定義method_exists()
– 檢查對像是否定義了方法<code>The class name is: Introspection I am a super class for the Child class. I'm Child class. I'm Introspection's child. Yes, Child is a subclass of Introspection.</code>
上述代碼的輸出應如下所示:
<code class="language-php"><?php interface ICurrencyConverter { public function convert($currency, $amount); } class GBPCurrencyConverter implements ICurrencyConverter { public $name = "GBPCurrencyConverter"; public $rates = array("USD" => 0.622846, "AUD" => 0.643478); protected $var1; private $var2; function __construct() {} function convert($currency, $amount) { return $this->rates[$currency] * $amount; } } if (interface_exists("ICurrencyConverter")) { echo "ICurrencyConverter interface exists.\n"; } $classes = get_declared_classes(); echo "The following classes are available:\n"; print_r($classes); if (in_array("GBPCurrencyConverter", $classes)) { print "GBPCurrencyConverter is declared.\n"; $gbpConverter = new GBPCurrencyConverter(); $methods = get_class_methods($gbpConverter); echo "The following methods are available:\n"; print_r($methods); $vars = get_class_vars("GBPCurrencyConverter"); echo "The following properties are available:\n"; print_r($vars); echo "The method convert() exists for GBPCurrencyConverter: "; var_dump(method_exists($gbpConverter, "convert")); } ?></code>
正如您可能已經猜到的那樣,interface_exists()
方法與第一個示例中討論的 class_exists()
方法非常相似。它確定是否已定義給定的接口,並採用接口名稱的字符串參數和可選的自動加載器布爾值。 get_declared_classes()
方法返回一個包含所有已定義類的名稱的數組,並且不帶任何參數。根據您加載的庫(編譯到 PHP 中或使用 require
/include
加載),可能存在其他類。 get_class_method()
將對象實例或表示所需類的字符串作為參數,並返回由類定義的方法名稱數組。請注意,在 ICurrencyConverter
類中定義的所有屬性以及 get_class_vars()
方法返回的所有屬性中,只有 $name
和 $rates
出現在輸出中。私有和受保護的屬性被跳過了。
PHP 反射 API
PHP 通過其反射 API 支持反射。正如您從 PHP 手冊中看到的那樣,反射 API 比內省機制要慷慨得多,並提供了大量的類和方法,您可以使用它們來完成反射任務。 ReflectionClass
類是 API 的主要類,用於對類、接口和方法應用反射,並提取有關所有類組件的信息。反射很容易在您的應用程序代碼中實現,並且與內省一樣,也非常直觀。以下是一個使用 ICurrencyConverter
接口和 Child
和 GBPCurrencyConverter
類相同定義來說明反射的示例:
<code class="language-php"><?php class Introspection { public function description() { echo "I am a super class for the Child class.\n"; } } class Child extends Introspection { public function description() { echo "I'm " . get_class($this) , " class.\n"; echo "I'm " . get_parent_class($this) , "'s child.\n"; } } if (class_exists("Introspection")) { $introspection = new Introspection(); echo "The class name is: " . get_class($introspection) . "\n"; $introspection->description(); } if (class_exists("Child")) { $child = new Child(); $child->description(); if (is_subclass_of($child, "Introspection")) { echo "Yes, " . get_class($child) . " is a subclass of Introspection.\n"; } else { echo "No, " . get_class($child) . " is not a subclass of Introspection.\n"; } } ?></code>
上述代碼的輸出應如下所示:
<code>The class name is: Introspection I am a super class for the Child class. I'm Child class. I'm Introspection's child. Yes, Child is a subclass of Introspection.</code>
getInterfaceNames()
方法返回一個包含類實現的接口名稱的數組。 getParentClass()
方法可以返回父類的 ReflectionClass
對象表示,如果不存在父類則返回 false。要列出 ReflectionClass
對象的名稱,您可以使用 getName()
方法,如上面的代碼所示。 getMethods()
方法檢索方法數組,並且可以將 ReflectionMethod::IS_STATIC
、IS_PUBLIC
、IS_PROTECTED
、IS_PRIVATE
、IS_ABSTRACT
和 IS_FINAL
的位掩碼組合作為可選參數,以根據可見性過濾列表。反射 API 提供了反射的良好實現,使您可以創建更複雜的應用程序,例如 ApiGen,但進一步討論超出了本文的目標。
總結
在本文中,您已經了解瞭如何使用 PHP 的內省函數和反射 API 來獲取有關類、接口、屬性和方法的信息。提取此信息的目的在於在運行時更好地了解您的代碼並創建複雜的應用程序。
(圖片來自 Fotolia)
(關於 PHP 中內省和反射的常見問題 (FAQ)) 此處省略了FAQ部分,因為篇幅過長,且與偽原創目標不符。 如有需要,可以單獨提出FAQ問題。
以上是PHP的內省和反射的詳細內容。更多資訊請關注PHP中文網其他相關文章!