詳解PHP反射技術的程式碼範例(圖文)
摘要
比起Java的反射,PHP中的反射可真的是良心之作。雖然從維修的角度來看,Java更勝一籌也更有優勢。但是繁瑣的處理也為Java的反射機制增加了一定的學習成本。
今天嘗試著使用PHP的反射技術來獲取類別的資訊。
核心操作可以在PHP的官方說明文件上看到,這裡用得最多的就是
getProperties getMethods
目標類別
為了更好的演示反射的結果以及維護,下面就先創建一個類,目錄結構如下:
<?phpclass Person { private $name; private $age; private $address; public function __construct($name, $age, $address) { $this->name = $name; $this->age = $age; $this->address = $address; } public function setter($key, $value) { exec ( "{$this}->" . $key . "={$value}" ); } /** * 通配型的getter方法不好用。 * <br /> * 原因: Object Person can not be converted to string. * * @param unknown $key * @return string */ public function getter($key) { return exec ( "$this" . "->{$key}" ); } /** * 模拟Java语言实现的getter方法。<br /> * * 缺点: 需要为每一个private属性提供单独的getter方法,使得代码略显臃肿。 */ public function getName() { return $this->name; } }class Grade { private $name; public function __construct($name) { $this->name = $name; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } }
加載問題
加載機制
#在正式進行在反射操作之前,先來探討一下__autoload
自動載入機制。顧名思義,自動化的進行載入(類,也可以是其他php檔案)唄。
對於更深層而言,這就牽涉到PHP解譯器的工作原理了。也就是說,我們不可能一個專案只寫一個php文件,相反,一個專案中可能會有數以百計的php文件,而且不可避免的會進行相互呼叫。
也就是說,我們在A檔案中宣告並實作了一個加法函數,而需要在B檔中進行呼叫。很明顯B檔案中根本沒有實作這個加法,所以PHP解譯器就沒辦法進行加法運算了。
這時候就需要讓PHP解釋器知道這個加法怎麼做,於是就需要require / include
包含了這個加法函數的A檔了。
這樣,PHP解譯器就知道如何解釋並執行咱們的PHP檔了。
與PHP相似的是,在Java語言中我們只需要在來源檔案前面加上import
語句,Java虛擬機器就能自動的在相關的類別資訊了。而且強型別的Java可以在編譯之前就發現這樣的問題,所以程式碼維護起來比較方便一點。而PHP則需要進行手動的 include/require
了。
但應該要清楚的是,這兩者換湯不換藥而已。
自動載入機制
但是如果對每一個要被引用的php檔案進行手動的載入的話,可能就要寫好多個這樣的載入語句了。所以為了方便處理這種問題,PHP5之後引入了自動載入機制。
void __autoload ( string $class )
$class
是要進行載入的類別的名稱,請注意是類別
的名稱。
怎麼使用?
既然自動載入機制這麼好,那我們要怎麼使用呢?
答案就是在需要載入其他類別檔案的php中,加入一個自訂的__autoload($class)
函數即可。 還是以剛才的文件AB來舉例。
檔案A中有一個寫好的類別Person,在檔案B中要進行使用。這時候在檔案B中加入一個__aotoload
函數即可。而且這個函數的寫法也比較的簡單(一切按照最簡思路來設計的話)。
function __autoload($class) { $filename = "$class.class.php"; if(!file_exists($filename)){ throw new RuntimeException("$filename 文件不存在!"); }else { require "$filename"; } }
PHP解釋器在掃描到檔案B的時候會先進行檢查,如果未引入目標類別Person,則會判斷有沒有實作__autoload
,如果存在則使用自動載入函數進行加載,否則報錯退出。
注意問題
雖然上面的自動載入函數比較簡單,但是現實中卻需要為此付出很多的“代價”,也就是被載入的類別文件的名稱要和類別保持一致(無需區分大小寫)。如:
要加载的类的名称为Person, 则该类所在的文件的名称需要为person.class.php,或者Person.class.php
而且,路徑問題也是一個比較棘手的問題,在這個簡易的自動載入函數中也不難看到,這裡他們位於同級目錄下,試想一下不滿足這個條件的情形,就可以知道這個自動載入函數的程式碼量將會多大了吧。
如此的話,也會違反了自動載入機制的設計的初衷。所以按照特定的目錄結構存放相關的類別文件是非常有必要的。
所謂:增加了冗餘的特點,卻帶來了容易維護的好處。
個人覺得,不妨按照Java語言的目錄結構來維護PHP程序,這樣會有意想不到的收穫的。
反射
下面正式進入反射的話題,在摘要部分已經提到。重點就在於ReflectionClass
的使用。
反射屬性
<?phprequire './bean/beans.php'; // Person 在beans.php文件中声明$protype = new ReflectionClass("Person"); // 可以添加一个参数,来进行过滤操作。如只获取public类型的属性 $properties = $protype->getProperties(); // 反射获取到类的属性信息 foreach ($properties as $property) { echo $property."<br />"; }
比比Java,要取得 private
屬性,PHP更為簡單。
反射方法
<?php require './bean/beans.php'; $protype = new ReflectionClass("Person"); $methods = $protype->getMethods(); foreach ($methods as $method) { echo $method->getName()."<br />"; }
另外,還可以加入篩選條件。給getMethods方法天機一個過濾參數即可。
filter过滤结果为仅包含某些属性的方法。默认不过滤。 ReflectionMethod::IS_STATIC、 ReflectionMethod::IS_PUBLIC、 ReflectionMethod::IS_PROTECTED、 ReflectionMethod::IS_PRIVATE、 ReflectionMethod::IS_ABSTRACT、 ReflectionMethod::IS_FINAL 的任意组合。
反射注释
注释信息,这里就以文档信息为例。
<?phprequire './bean/beans.php'; $protype = new ReflectionClass ( "Person" ); $properties = $protype->getProperties (); // 反射获取到类的属性信息 foreach ( $properties as $property ) { echo $property . ":"; $doc = $property->getDocComment (); echo " " . $doc . "<br />"; e cho "--------------------------------------------------------" . "<br />"; }$methods = $protype->getMethods(); foreach ($methods as $method) { echo $method->getName()."<br />"; $doc = $method->getDocComment (); echo " " . $doc . "<br />"; echo "--------------------------------------------------------" . "<br />"; }
反射实例化
詳解PHP反射技術的程式碼範例(圖文)
<?phprequire './bean/beans.php'; $protype = new ReflectionClass ( "Person" );// 模拟数据库中获取到的值,以关联数组的形式抛出 $values = array( "name"=>"郭璞", "age"=> 21, "address"=>"辽宁省大连市");// 开始实例化 $instance = $protype->newInstanceArgs($values); print_r($instance);// var_dump($instance); echo $instance->getName();
反射Grade类
<?phprequire './bean/beans.php';$classprotype = new ReflectionClass("Grade");$class = $classprotype->newInstanceArgs(array("name"=>"大三")); var_dump($class);echo $class->getName();
执行类的方法
$instance->getName(); // 执行Person 里的方法getName// 或者: $method = $class->getmethod('getName'); // 获取Person 类中的getName方法$method->invoke($instance); // 执行getName 方法// 或者:$method = $class->getmethod('setName'); // 获取Person 类中的setName方法$method->invokeArgs($instance, array('snsgou.com'));
总结
回顾一下,本次试验演示了PHP中的反射技术,对比分析了Java语言的反射技术的实现。也只能说各有利弊吧。
在Java中,反射技术是编写框架的基础。虽然在PHP中反射技术不是特别的重要,而且用的时候约束也比较多,稍显鸡肋。但是比葫芦画瓢的话,还是可以做出一些有用的小工具的。
以上是詳解PHP反射技術的程式碼範例(圖文)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

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

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。
