PHP 中以雙底線 __ 開頭的類別方法稱為魔術方法,它們在特定情況下會被自動呼叫,讓物件能對語言內建行為做出自訂回應。常見的包括 __construct、__destruct、__call、__get、__set、__toString、__invoke、__sleep、__wakeup、__clone 等。
物件建立與銷毀時自動觸發,用於初始化資源與釋放清理。
當物件被當作字串使用時(如 echo $obj)自動呼叫,必須回傳字串。
class User {
public $name;
public function __construct($name) { $this->name = $name; }
public function __toString() { return "User: {$this->name}"; }
}
echo new User('Alice'); // 輸出: User: Alice
處理不可存取(私有、受保護或不存在)屬性的讀寫檢查:
__set($name, $value):寫入不可存取屬性時觸發。__get($name):讀取不可存取屬性時觸發。__isset($name):對不可存取屬性呼叫 isset() 或 empty() 時觸發。__unset($name):對不可存取屬性呼叫 unset() 時觸發。呼叫不存在或不可存取的方法時觸發:
__call($name, $arguments):物件語境下。__callStatic($name, $arguments):靜態語境下(PHP 5.3+)。當物件被當作函式呼叫時觸發(PHP 5.3+),實現可呼叫物件。
class Multiplier {
public function __invoke($x) { return $x * 2; }
}
$double = new Multiplier();
echo $double(5); // 10
序列化(serialize())與反序列化(unserialize())時自動呼叫:
__sleep():必須回傳需序列化的屬性名稱陣列,可排除敏感或資源型屬性。__wakeup():反序列化後重新建立資源連線等。物件被 clone 關鍵字複製時觸發,預設為淺拷貝,可在其中實作深拷貝邏輯。
var_export() 匯出類別時呼叫的靜態方法(PHP 5.1+),用於重建物件狀態。
class DynamicEntity {
private $data = [];
public function __set($k, $v) { $this->data[$k] = $v; }
public function __get($k) { return $this->data[$k] ?? null; }
public function __call($method, $args) {
if (str_starts_with($method, 'get')) {
$field = lcfirst(substr($method, 3));
return $this->data[$field] ?? null;
}
throw new BadMethodCallException("Method $method not found");
}
}
$e = new DynamicEntity();
$e->email = 'test@example.com';
echo $e->getEmail(); // test@example.com
__get/__set 應配合 PHPDoc @property 標註,提升 IDE 提示。__call 中處理複雜業務邏輯,建議轉交給具體方法。__sleep/__wakeup、__serialize/__unserialize PHP 7.4+)優先使用新介面。魔術方法是 PHP 物件導進階功能的核心,掌握它們能讓你設計出更靈活、富有表達力的類別。實務上請依場景審慎選用,並搭配嚴格的型別宣告與文件註解,確保程式碼可維護性。