PHP獲取類私有屬性的3種方法

2022-09-26 02:39:11 字數 1996 閱讀 6268

今天在推上看到一條獲取php類私有屬性的推文,感覺很有意思:

順著推文聯想,還有其他方式嗎?經過自己的測試及網上答案,總結出三種方法:

1. 反射

反射可以獲取類的詳細資訊,要獲取私有屬性的值,只需將對應屬性的reflectionproperty例項設定為可訪問再取值即可。示例**如下:

namespace tlanyan;

classwww.cppcns.com foo

// 獲取反射類及反射屬性

$class = new \reflectionclass(foo::class);

$property = $class->getproperty("bar");

// 設定屬性可訪問

$property->setaccessible(true);

$foo = new foo;

// 獲取物件屬性值

// 注意:只能通過 reflectionproperty 例項的 getvalue 方法訪問

// 不能這樣直接訪問: $foo->b程式設計客棧ar;

echo $property->getvalue($foo), php_eol:

// 輸出: foo bar!

本人之前寫過「php回顧之反射」一文,比較詳細的介紹了反射及用法,有興趣的閱讀參考。

2. 轉換成陣列

這種方法用將物件強制轉換成陣列,再通過鍵獲取其值。示例**如下:

class foo

$foo = new foo;

// 強制轉型

$attrs = (array)$foo;

// 拼接key,注意 "\0" 不能改成單引號!

$key = "\0" . foo::class . "\0" . "bar";

echo $attrs[$key], php_eol;

// 輸出: foo bar!

上述**中key的拼接方式比較詭異,key規則如下:

注意 \0 是乙個字元(不程式設計客棧是兩個),對應的ascii碼是數字0。程式設計時要用雙引號將其引起來。不能使用單引號,否則轉義失效,那就是兩個字元。如果你有c語言基礎,應該知道 \0 就是字串的結束符。這個符號直接輸出不會顯示,但可以通過strlen或者ord讓其現形:

foreach ($attrs as $key => $value)

echo php_eol;

}// 輸出

// key:foobar, key length:8, ascii: 0 70 111 111 0 98 97 114

// foobar 有6個字元,加上兩個不顯示字元,所以長度是8

還需要注意拼接private屬性時類名應該是 「完全限定類名」 ,建議通過foo::class的方式獲取。

與強制轉換成陣列類似的另一種方法是serialize,但是serialize比較慢,並且序列化後的字串更難辨認結構和處理,不建議使用。

3. 閉包

文章開頭的推特截圖已經展示了閉包的用法,其中call方法在php7中引入,另乙個是php5.4引入的bindto。call和bindto的用法示例如下:

namespace tlanyan;

class foo

$foo = new foo;

// 閉包(匿名函式)是php5.3引入的功能

$closure = function() ;

// php5.4起支援bindto方法

$method = $closure->bindto($foo, foo::class);

echo $method(), php_eol;

// php7引入call方法,可繫結this直接執行

echo $closure->call($foo), php_eol;

bindto方法的第二個引數注意傳入物件的 「完全限定類名」,指示函式應該放置在該類的作用域下,從而可以訪問私有屬性。

總結效能: 陣列 > 反射 > 閉包

易用性: 閉包 > 陣列 > 反射

推薦: 閉包 > 反射 > 陣列

PHP獲取POST資料的3種方法

一 php獲取post資料的幾種方法 方法1 最常見的方法是 post fieldname 解釋 也就是表單post過來的資料 方法2 file get contents php input 說明 允許讀取 post 的原始資料。和 http raw post data 比起來,它給記憶體帶來的壓力...

php中類外部訪問類私有屬性的方法

我們都知道,類的私有屬性在類外部是不可訪問的,包括子類中也是不可訪問的。比如如下 class example1 r function example1 e a new example1 var dump r a 執行結果 fatal error cannot access private prope...

Node獲取路徑的3種方法

node提供了3種獲取路徑的方法 在當前目錄下,執行node const require path console.log dirname dirname console.log resolve resolve console.log cwd process.cwd dirname d new no...