php5之後實作了一些魔術方法還是比較有趣的,之前一直用過程導向的程式設計方法,對oop研究的比較少,最近在看oop的東西,還是比較有趣的。
魔術方法這些東西,感覺很大一部分就是為了偷懶用的,記得最早寫php的時候,那時候做博客,用的是國外的一個叫lifetype的開源框架,那時候還是php4. 3,但是那個框架裡全部實作了對象,所有的資料都被封裝到對像中。
於是當從db裡select出來一堆東西之後,還要逐個循環封裝成對象,每一個字段也要實現getField()和getField()方法,寫起來還真有點麻煩,感覺就是在做重複性的工作。
那麼get(),set(),call(),callStatic()這幾個魔術方法的誕生,就完全解決了這個問題。
get()和set()是針對類別中屬性的而call()是針對方法的,callStatic() 是針對靜態類別的方法。
一、get()和set()魔術方法:
當實例化一個物件後,呼叫類別中不存在或沒有權限存取的屬性的時候,php會預設呼叫get()方法,這樣做,不僅可以少些很多程式碼,讓結構更清晰,而且還提供了一條外部存取類別的私有成員的一種方法。
例如:
<?php class testGet { private $name = 'test'; } $test = new testGet(); $test->name;
上面的程式碼,如果我們運行,會報一個錯誤:PHP Fatal error: Cannot access private property testGet::$name in /Library/WebServer/ Documents/workspace/learn/call/a.php on line 7
#但是我們修改一下,透過get()方法可以存取
<?php class testGet { private $name = 'test'; function get($property) { if ( isset($this->$property) ) return $this->$property; else return NULL; } } $test = new testGet(); echo $test->name . PHP_EOL;
程式碼改成這樣之後我們再訪問就沒有問題。
注意:如果把屬性定義成是static的,那麼透過get()存取也會報錯。原因是static的成員,是屬於類別本身的,不因為實例化而改變,可以自己測試。
利用set()方法,可以禁止動態建立類別屬性,這樣可以很好的避免給後來開發者,或是程式維護者帶來不必要的麻煩。
funciton set($property) {
//$property接收的是屬性的名字
}
是實話,oop這個東西的設計,會摻雜很多設計者自己的思想,如果沒有文檔,後來者去讀程式碼還是很費勁的,當然和後來者的水平也有很大關係。
下面是一個get和set配合使用的範例:
<?php class testGet { private $name = 'test'; function get($property) { if ( isset($this->$property) ) return $this->$property; else return NULL; } public function set($property, $value) { if ( isset($this->$property) ) $this->$property = $value; else return NULL; } } $test = new testGet(); $test->name = 'my test name'; echo $test->name . PHP_EOL;
function set($property, $value) {
/ /$property接收的屬性的名字
//$value接收的是屬性的值
}
二、call()和callStatic()方法:
當物件呼叫類別中一個不存在或沒有權限存取的方法的時候,就會自動呼叫call()方法。
記得以前有個同事問我,tp框架中為什麼有很多底層的方法沒有,但是在上層還能調用,其實就是call()這個方法在起作用。
如果你不知道這個方法,那麼一定會很疑惑,而且問題也不好定位。
<?php abstract class Obj { private $objData = array(); /** * call魔术方法,如果对象请求的方法不存在或者没有权限访问的时候 * 调用魔术方法 */ public function call($name, $args) { $field = preg_match('/^get(\w+)/', $name, $matches); if ( $field && $matches[1] ) return $this->objData[strtolower($matches[1])]; $field = preg_match('/^set(\w+)/', $name, $matches); if ( $field && $matches[1] ) { return $this->objData[strtolower($matches[1])] = $args[0]; } } } class User extends Obj { } $user = new User(); $user->setName('test'); echo $user->getName();
User類別什麼都沒乾,但是透過繼承類別的call()方法,把所有的事都做了(getName和setName)。
function call($methodName, $args) {
#//$methodName呼叫的方法名稱
//$args傳遞的參數陣列
#}
和call()對應的是callStatic()方法,是位元靜態類別的靜態方法服務的。
範例:
<?php abstract class Obj { private static $objData = array(); /** * call魔术方法,如果对象请求的方法不存在或者没有权限访问的时候 * 调用魔术方法 */ public static function callStatic($name, $args) { $field = preg_match('/^get(\w+)/', $name, $matches); if ( $field && $matches[1] ) return self::$objData[strtolower($matches[1])]; $field = preg_match('/^set(\w+)/', $name, $matches); if ( $field && $matches[1] ) { return self::$objData[strtolower($matches[1])] = $args[0]; } } } class User extends Obj { } User::setName('test'); echo User::getName() . PHP_EOL;
三、延遲靜態綁定:static這個物件
以上是php的魔術方法__get(),__set(),__call(),__callStatic()以及static用法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!