PHP獲取類私有屬性的3種方法
今天在推上看到一條獲取PHP類私有屬性的推文,感覺(jué)很有意思:
順著推文聯(lián)想,還有其他方式嗎?經(jīng)過(guò)自己的測(cè)試及網(wǎng)上答案,總結(jié)出三種方法:
1. 反射
反射可以獲取類的詳細(xì)信息,要獲取私有屬性的值,只需將對(duì)應(yīng)屬性的ReflectionProperty實(shí)例設(shè)置為可訪問(wèn)再取值即可。示例代碼如下:
namespace tlanyan; class Foo { private $bar = "Foo bar!"; } // 獲取反射類及反射屬性 $class = new \ReflectionClass(Foo::class); $property = $class->getProperty("bar"); // 設(shè)置屬性可訪問(wèn) $property->setAccessible(true); $foo = new Foo; // 獲取對(duì)象屬性值 // 注意:只能通過(guò) ReflectionProperty 實(shí)例的 getValue 方法訪問(wèn) // 不能這樣直接訪問(wèn): $foo->bar; echo $property->getValue($foo), PHP_EOL: // 輸出: Foo bar!
本人之前寫(xiě)過(guò)“PHP回顧之反射”一文,比較詳細(xì)的介紹了反射及用法,有興趣的閱讀參考。
2. 轉(zhuǎn)換成數(shù)組
這種方法用將對(duì)象強(qiáng)制轉(zhuǎn)換成數(shù)組,再通過(guò)鍵獲取其值。示例代碼如下:
class Foo { private $bar = "Foo bar!"; } $foo = new Foo; // 強(qiáng)制轉(zhuǎn)型 $attrs = (array)$foo; // 拼接key,注意 "\0" 不能改成單引號(hào)! $key = "\0" . Foo::class . "\0" . "bar"; echo $attrs[$key], PHP_EOL; // 輸出: Foo bar!
上述代碼中key的拼接方式比較詭異,key規(guī)則如下:
public
屬性, key是 屬性名;protected
屬性,key是 \0*\0屬性名;private
屬性, key是 \0類名\0屬性名。
注意 \0 是一個(gè)字符(不是兩個(gè)),對(duì)應(yīng)的ASCII碼是數(shù)字0。編程時(shí)要用雙引號(hào)將其引起來(lái)。不能使用單引號(hào),否則轉(zhuǎn)義失效,那就是兩個(gè)字符。如果你有C語(yǔ)言基礎(chǔ),應(yīng)該知道 \0 就是字符串的結(jié)束符。這個(gè)符號(hào)直接輸出不會(huì)顯示,但可以通過(guò)strlen
或者ord
讓其現(xiàn)形:
foreach ($attrs as $key => $value) { echo "key:$key", ", key length:", strlen($key), ", ascii: "; for ($i = 0; $i < strlen($key); ++ $i) { echo ord($key[$i]), " "; } echo PHP_EOL; } // 輸出 // key:Foobar, key length:8, ascii: 0 70 111 111 0 98 97 114 // Foobar 有6個(gè)字符,加上兩個(gè)不顯示字符,所以長(zhǎng)度是8
還需要注意拼接private
屬性時(shí)類名應(yīng)該是 “完全限定類名” ,建議通過(guò)Foo::class
的方式獲取。
與強(qiáng)制轉(zhuǎn)換成數(shù)組類似的另一種方法是serialize
,但是serialize
比較慢,并且序列化后的字符串更難辨認(rèn)結(jié)構(gòu)和處理,不建議使用。
3. 閉包
文章開(kāi)頭的推特截圖已經(jīng)展示了閉包的用法,其中call
方法在PHP7中引入,另一個(gè)是PHP5.4引入的bindTo
。call
和bindTo
的用法示例如下:
namespace tlanyan; class Foo { private $bar = "Foo bar!"; } $foo = new Foo; // 閉包(匿名函數(shù))是PHP5.3引入的功能 $closure = function() { return $this->bar; }; // PHP5.4起支持bindTo方法 $method = $closure->bindTo($foo, Foo::class); echo $method(), PHP_EOL; // PHP7引入call方法,可綁定this直接執(zhí)行 echo $closure->call($foo), PHP_EOL;
bindTo
方法的第二個(gè)參數(shù)注意傳入對(duì)象的 “完全限定類名”,指示函數(shù)應(yīng)該放置在該類的作用域下,從而可以訪問(wèn)私有屬性。
總結(jié)
性能: 數(shù)組 > 反射 > 閉包
易用性: 閉包 > 數(shù)組 > 反射
推薦: 閉包 > 反射 > 數(shù)組
以上就是PHP獲取類私有屬性的3種方法的詳細(xì)內(nèi)容,更多關(guān)于PHP獲取類私有屬性的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
php實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增刪改查
本文給大家介紹的是PHP連接數(shù)據(jù)庫(kù)以及實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增刪改查功能的方法及示例代碼,希望對(duì)大家學(xué)習(xí)php能夠有所幫助2017-02-02理解php Hash函數(shù),增強(qiáng)密碼安全
服務(wù)器和數(shù)據(jù)庫(kù)的資料偶爾會(huì)被竊取,因此需要保證發(fā)生這種情況時(shí)一些重要的用戶數(shù)據(jù),比如密碼,是別人無(wú)法獲取的。這里我們將要討論Hash的原理,以及它是如何保護(hù)Web應(yīng)用程序中的密碼安全的。2011-02-02PHP源代碼數(shù)組統(tǒng)計(jì)count分析
偶然在百度知道中看到有個(gè)同學(xué)問(wèn)起count及strlen的效率問(wèn)題,好吧這個(gè)問(wèn)題我當(dāng)初沒(méi)理解透徹,認(rèn)為其不屬兩個(gè)不一樣的東西不可比較,后來(lái)看了樓主的回復(fù)才反應(yīng)過(guò)來(lái),所以自己也去找了下源碼查看下?,F(xiàn)在總結(jié)下查看到的結(jié)果并記錄之。2011-08-08Zend Framework中的簡(jiǎn)單工廠模式 圖文
某天又然后想到好久沒(méi)復(fù)習(xí)設(shè)計(jì)模式了。綜合一下,復(fù)習(xí)一個(gè)設(shè)計(jì)模式之后在ZF中找一下使用這模式的源碼吧,不讀所有源碼,讀讀比較”高級(jí)”的部分吧,要說(shuō)模式,暫時(shí)不知道是不是所有模式ZF里面都有,但是應(yīng)該有足夠的模式夠我最近看了,在說(shuō)可以找找其他開(kāi)源的軟件來(lái)找模式2012-07-07PHP編碼規(guī)范-php coding standard
標(biāo)準(zhǔn)化問(wèn)題在某些方面上讓每個(gè)人頭痛,讓人人都覺(jué)得大家處于同樣的境地。這有助于讓這些建議在許多的項(xiàng)目中不斷演進(jìn),許多公司花費(fèi)了許多星期逐子字逐句的進(jìn)行爭(zhēng)論。2007-03-03