對PHP5中__set和__get的理解
阿新 • • 發佈:2019-01-24
引用一個偷學來的概念:
成員變數是一個“內”概念,反映類的結構構成。屬性是一個“外”概念,反映的是類的邏輯意義。
成員變數沒有讀寫許可權的控制,而屬性可以指定只讀只寫,或可讀或可寫。
成員變數不對讀出做任何後處理,不對寫入做任預處理,而屬性可以。
public成員變數可以視作沒有任何後處理讀操作以及沒有任何預處理寫操作的屬性,而private由於外部不可見,不符合屬性的“外”概念,所以不能視為屬性。
大多數情況,屬性會由成員變數來表示,但是屬性和成員變數沒有必然的對應關係。
通常情況下,將類的成員變數定義為private這樣好處一個是為了類的封裝性,同時能體現良好的變成習慣。但是對於成員變數的讀寫操作是非常繁瑣的,因此,在PHP5中定義了兩個魔法方法,__set()和__get(),在讀取一個不存在的成員變數時候,會自動呼叫_set和_get,這兩個方法不是預設存在,需要我們手動新增到類中。
class Fruit { private $color; private $weight; public function __set($name,$value){ $this->$name = $value; } public function __get($name){ return $this->$name; } }
以上類Fruit中有兩個私有的成員變數,設定了__set和__get以後,可以直接通過下面這種方式對成員變數進行呼叫。
$fruit = new Fruit(); $fruit->color = 'red'; echo $fruit->如果沒有__set和__get,直接通過$fruit->color這種方式呼叫,則會出錯。color;
利用這一特點,可以實現對單一屬性的set和get操作,同時在讀操作的時候進行後處理以及在寫操作的時候進行預處理。
class Fruit { private $color; private $weight; public function __get($name) // 這裡$name是屬性名 { $getter = 'get' . $name; // getter函式的函式名 if (method_exists($this, $getter這樣可以在屬性寫操作的時候,對屬性賦值進行trim處理,對屬性讀的時候,添加了一個一個字串。)) { return $this->$getter(); // 呼叫了getter函式 } elseif (method_exists($this, 'set' . $name)) { throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name); } else { throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name); } } // $name是屬性名,$value是擬寫入的屬性值 public function __set($name, $value) { $setter = 'set' . $name; // setter函式的函式名 if (method_exists($this, $setter)) { $this->$setter($value); // 呼叫setter函式 } elseif (method_exists($this, 'get' . $name)) { throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name); } else { throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name); } } public function setColor($value){ if(trim($value)){ $this->color = $value; } } public function getColor(){ return 'The color is ' . $this->color; } }
$fruit = new Fruit(); $fruit->color = ' red'; echo $fruit->color;列印結果如下:
The color is red
同樣,Yii2框架中Object類就是適用這個特性實現對private成員變數的setter和getter。