PHP 魔術方法完整清單:17 個魔術方法分類、觸發時機與命名規範
PHP 類別中以雙底線 __ 開頭的方法為魔術方法,在特定情況下自動觸發。本文整理所有 17 個魔術方法分類清單、觸發條件與命名規範建議。
完整魔術方法清單(依功能分類)
物件生命週期
| 方法 | 觸發時機 | 參數/回傳 |
__construct() | 物件實例化 new Class() | 參數任意,無回傳值要求 |
__destruct() | 物件銷毀(參考計數歸零、腳本結束) | 無參數,無回傳值 |
__clone() | clone $obj 淺複製後 | 無參數,無回傳值 |
屬性存取攔截
| 方法 | 觸發時機 | 參數/回傳 |
__get($name) | 讀取不可見屬性 $obj->prop | 參數:屬性名;必須回傳值 |
__set($name, $value) | 寫入不可見屬性 $obj->prop = $val | 參數:屬性名、值;無回傳值要求 |
__isset($name) | isset($obj->prop) 不可見屬性 | 參數:屬性名;必須回傳 bool |
__unset($name) | unset($obj->prop) 不可見屬性 | 參數:屬性名;無回傳值要求 |
方法呼叫攔截
| 方法 | 觸發時機 | 參數/回傳 |
__call($name, $args) | 呼叫不可見實例方法 $obj->method() | 參數:方法名、引數陣列;必須回傳值 |
__callStatic($name, $args) | 呼叫不可見靜態方法 Class::method() | 參數:方法名、引數陣列;必須回傳值 |
序列化與字串轉換
| 方法 | 觸發時機 | 參數/回傳 |
__sleep() | serialize($obj) 前 | 無參數;必須回傳屬性名陣列 |
__wakeup() | unserialize($str) 後 | 無參數;無回傳值要求 |
__serialize() | serialize($obj) 前 (PHP 7.4+) | 無參數;回傳關聯陣列 |
__unserialize() | unserialize($str) 後 (PHP 7.4+) | 參數:資料陣列;無回傳值 |
__toString() | 物件當字串使用 echo $obj | 無參數;必須回傳字串 |
其他特殊用途
| 方法 | 觸發時機 | 參數/回傳 |
__invoke() | 物件當函數呼叫 $obj() | 參數任意;回傳值任意 |
__set_state($array) | var_export() 輸出類別時 (static) | 參數:屬性陣列;回傳物件實例 |
__debugInfo() | var_dump($obj) 時 (PHP 5.6+) | 無參數;回傳顯示用關聯陣列 |
命名規範與最佳實踐
1. 命名規範
- 所有魔術方法必須以雙底線
__ 開頭
- 方法名稱區分大小寫,標準為小寫(
__construct 非 __Construct)
- 使用者自訂方法避免使用
__ 開頭,防止與未來 PHP 版本新增魔術方法衝突
2. 實作建議
| 魔術方法 | 關鍵實作要點 |
__construct | 初始化資源、驗證參數、建立連線 |
__destruct | 釋放資源、關閉連線、寫入快取 |
__get/__set | 使用私有陣列儲存,避免遞迴;加入驗證邏輯 |
__call | 動態代理、方法不存在時的 fallback、API 客戶端 |
__sleep | 回傳需序列化屬性名,排除資源/連線/大物件 |
__wakeup | 重新建立連線、初始化資源 |
__toString | 回傳人類可讀字串,避免拋出例外 |
__invoke | 實作可呼叫物件、策略模式、函數式風格 |
__debugInfo | 隱藏敏感資料(密碼、Token)、簡化除錯輸出 |
3. 常見錯誤
- 遞迴無限循環:在
__get 中讀取 $this->name 觸發再次 __get
- __destruct 不可靠:
exit()、致命錯誤、process kill 可能跳過
- __sleep 回傳錯誤:未回傳陣列或包含不存在屬性導致序列化失敗
- __toString 拋出例外:會產生
E_RECOVERABLE_ERROR,必須回傳字串
快速查詢卡
// 物件建立/銷毀
__construct() new Class()
__destruct() 物件銷毀
__clone() clone $obj
// 屬性存取
__get($n) $obj->prop (讀取不可見)
__set($n,$v) $obj->prop = $val (寫入不可見)
__isset($n) isset($obj->prop) (不可見)
__unset($n) unset($obj->prop) (不可見)
// 方法呼叫
__call($n,$a) $obj->method() (不可見)
__callStatic($n,$a) Class::method() (不可見)
// 序列化
__sleep() serialize() 前
__wakeup() unserialize() 後
__serialize() serialize() 前 (7.4+)
__unserialize() unserialize() 後 (7.4+)
// 其他
__toString() (string)$obj / echo $obj
__invoke() $obj()
__set_state() var_export() 靜態
__debugInfo() var_dump() (5.6+)