2013年5月11日 星期六

PHP 的 __get、__set 魔術方法

看到 C# 的 get、set  時,想到 PHP 是否也有類似的用法。

參考:
http://php.net/manual/en/language.oop5.overloading.php

說明:
public void __set ( string $name , mixed $value )
public mixed __get ( string $name )
__get 執行時機:嘗試取得不存在的屬性無權訪問的屬性
__set 執行時機:嘗試設定不存在的屬性無權訪問的屬性

範例:
class aa{
    private $pri = "private test";
    public $pub = "public test";
    
    public function __get($name){
        echo "執行 __get()=> name: $name";
    }
    
    public function __set($name,$value){
        echo "執行 __set()=> name: $name , value: $value";
    }
}

$obj = new aa();
//private 屬性
$obj->pri; //執行 __get()=> name: pri
$obj->pri = "xyz";//執行 __set()=> name: pri , value: xyz

//public 屬性
$obj->pub; //不會執行 __get()
$obj->pub = "xyz"; //不會執行 __get()

//不存在的屬性
$obj->no; //執行 __get()=> name: no
$obj->no = "xyz"; //執行 __set()=> name: no , value: xyz

實例應用:
若原本有一 class ,有一 public 的屬性,整個系統程式到處直接存取、設定這個屬性。如下。
class aa{
    public $month = 1;
}
$obj = new aa();
echo $obj->month; //1
$obj->month = 13;
echo $obj->month; //13

若今天想把 echo $obj->month 的輸出,後面多加一個字 "月" (例:1月),
且 $obj->month = 13 這種大於12的設定改成 $obj->month = 12。
如果不想修改全部有使用到的地方,
可利用魔術方法 __get、__set 如下修改。
class aa{
    private $month = 1; // public 改為 private
    
    public function __get($name){
        switch($name){
            case "month";
                return $this->month . "月";
            break;
            default:
                return null;
        }
    }
    
    public function __set($name,$value){
        switch($name){
            case "month";
                if($value < 1){
                    $this->month = 1;
                }else if($value > 12){
                    $this->month = 12;
                }else{
                    $this->month = $value;
                }
            break;
        }
    }
}
$obj = new aa();
echo $obj->month; //1月
$obj->month = 13;
echo $obj->month; //12月

沒有留言:

張貼留言