封裝核心
- 屬性宣告為
private,對外不可直接存取。
- 提供
public 的 getter/setter 控制讀寫邏輯(驗證、轉換、日誌)。
- 方法亦可
private,隱藏內部實作細節。
魔術方法自動攔截
| 方法 | 觸發時機 | 參數 |
__get($name) | 讀取不可存取屬性(不存在或 private/protected) | $name: 屬性名 |
__set($name, $value) | 寫入不可存取屬性 | $name, $value |
__isset($name) | 對不可存取屬性呼叫 isset() 或 empty() | $name |
__unset($name) | 對不可存取屬性呼叫 unset() | $name |
完整範例:Person 類別
<?php
class Person {
private $name;
private $age;
private $sex;
public function __construct($name, $age, $sex) {
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
// 直接讀取私有屬性時自動呼叫
private function __get($prop) {
if ($prop === 'age' && $this->age > 40) return $this->age - 10; // 讀取邏輯
return $this->$prop ?? null;
}
// 直接寫入私有屬性時自動呼叫
private function __set($prop, $value) {
if ($prop === 'age' && ($value > 100 || $value < 0)) return; // 驗證
$this->$prop = $value;
}
private function __isset($prop) {
return isset($this->$prop);
}
private function __unset($prop) {
unset($this->$prop);
}
// 公開介面(建議慣用)
public function setAge($age) {
if ($age > 100 || $age < 0) return;
$this->age = $age;
}
public function getAge() {
if ($this->age < 30) return $this->age;
if ($this->age < 40) return $this->age - 5;
if ($this->age < 50) return $this->age;
return $this->age - 15;
}
public function say() {
echo "我是 {$this->name},{$this->getAge()} 歲,{$this->sex}
";
$this->run(); // 呼叫私有方法
}
private function run() { echo '跑步中...
'; }
}
/* 測試 */
$p = new Person('張三', 25, '男');
$p->say(); // 正常輸出
$p->setAge(30); // 透過 setter
echo $p->getAge(); // 透過 getter
$p->age = 35; // 觸發 __set
echo $p->age; // 觸發 __get
unset($p->name); // 觸發 __unset
echo isset($p->name) ? '存在' : '不存在'; // 觸發 __isset
最佳實務
- 魔術方法適合動態屬性(如 ORM 模型對應資料表欄位)。
- 固定屬性優先使用明確 getter/setter,IDE 支援好、靜態分析友善、效能稍佳。
- 魔術方法中避免重型邏輯,影響除錯與效能。