首頁 > 後端開發 > php教程 > php的魔術方法__get(),__set(),__call(),__callStatic()以及static用法詳解

php的魔術方法__get(),__set(),__call(),__callStatic()以及static用法詳解

伊谢尔伦
發布: 2023-03-12 13:50:01
原創
3245 人瀏覽過

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 = &#39;test&#39;;
}
$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 = &#39;test&#39;;

  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 = &#39;test&#39;;

  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 = &#39;my test name&#39;;
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(&#39;/^get(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] )
                return $this->objData[strtolower($matches[1])];
            $field = preg_match(&#39;/^set(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] ) { 
                return $this->objData[strtolower($matches[1])] = $args[0];
            }   
        }   
}
class User extends Obj
{
        
}
$user = new User();
$user->setName(&#39;test&#39;);
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(&#39;/^get(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] )
                return self::$objData[strtolower($matches[1])];
            $field = preg_match(&#39;/^set(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] ) { 
                return self::$objData[strtolower($matches[1])] = $args[0];
            }   
        }   
    }
    class User extends Obj 
    {
    
    }
    User::setName(&#39;test&#39;);
    echo User::getName() . PHP_EOL;
登入後複製

三、延遲靜態綁定:static這個物件

以上是php的魔術方法__get(),__set(),__call(),__callStatic()以及static用法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
php
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板