一、介紹
?PHP魔術方法是以雙下劃線__開頭的一組特殊方法,用于在對象生命周期、屬性訪問、方法調用等場景中實現自動化操作。?簡化面向對象編程。
二、17個現有的魔術方法
(一)、對象生命周期相關
1、__construct()
? ? ? ? 類的構造函數方法,具有構造函數的類會在每次創建新對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作。
2、__destruct()
? ? ? ? 類的析構函數,會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執行。
3、__get()
????????讀取不可訪問(protected 或 private)或不存在的屬性的值時,__get()?會被調用。
4、__set()
? ? ? ? 在給不可訪問(protected 或 private)或不存在的屬性賦值時,__set()?會被調用。
5、__isset()
? ? ? ?對不可訪問(protected 或 private)或不存在的屬性調用?isset()?或?empty()?時,__isset()?會被調用。
6、__unset()
? ? ? ? 當對不可訪問(protected 或 private)或不存在的屬性調用?unset()?時,__unset()?會被調用。
7、__call()
? ? ? ?調用不存在或不可訪問(protected 或 private)的方法時調用
8、__callStatic()
? ? ? ? 調用不存在或不可訪問(protected 或 private)靜態方法時調用
9、__clone()
? ? ? ? 復制對象時會執行
10、__set_state()
????????當調用var_export()導出類時,此方法會被調用。
var_export()?函數返回關于傳遞給該函數的變量的結構信息,它和?var_dump()?函數類似,不同的是其返回的表示是合法的 PHP 代碼。
11、__debugInfo()
????????使用print_r,var_dump、print、dump等時調用,可設置打印信息格式
12、__tostring()
? ? ? ? ?類被當成字符串調用時執行
13、__invoke()
? ? ? ? ?類被當成方法調用時執執行
14、__sleep()
????????serialize()方法被執行前調用
????????此功能可以用于清理對象,并返回一個包含對象中所有應被序列化的變量名稱的數組。 如果該方法未返回任何內容,則?null
?被序列化,并產生一個?E_NOTICE
?級別的錯誤。
serialize() 函數用于序列化對象或數組,并返回一個字符串。
15、__wakeup()
? ? ? ? unserialize()方法被執行前調用
????????經常用在反序列化操作中,例如重新建立數據庫連接,或執行其它初始化操作。
unserialize()?函數用于將通過?serialize()函數序列化后的對象或數組進行反序列化,并返回原始的對象結構。
16、__serialize()? ?【PHP7.4+之后被引入,當同__sleep()魔術方法同時存在時,__serialize()會被執行,__sleep()會被忽略】
????????serialize()方法被執行前調用。
????????它必須以一個代表對象序列化形式的 鍵/值 成對的關聯數組形式來返回,如果沒有返回數組,將會拋出一個?TypeError?錯誤。
17、__unserialize()?【PHP7.4+之后被引入,當同__wakeup()魔術方法同時存在時,__unserialize()會被執行,__wakeup()會被忽略】
?????????unserialize()方法被執行前調用
三、被廢棄的魔術方法
18、__autoload() 【PHP 7.2.0 起被廢棄,并自 PHP 8.0.0 起被移除】
? ? ? ? 嘗試加載未被定義的類
四、最佳實踐與注意事項
- 避免濫用:
????????魔術方法會增加代碼隱性邏輯,過度使用會增加代碼維護難度。日常編程時推薦優先使用常規 OOP 設計(如公共方法),僅在必要時使用魔術方法。
- 性能考量:
????????動態方法調用(__call/__callStatic)存在額外的函數調用開銷,高頻場景需謹慎評估。
- 兼容性:
????????部分魔術方法隨著php版本的升級,逐步被棄用,如__autoload()。
- 安全控制:
????????在 __get/__set 等方法中,需對輸入進行嚴格過濾,避免代碼注入或數據泄露(如動態調用 __call 時驗證方法名)。
五、總結
魔術方法是 PHP 面向對象編程中的“約定式鉤子”,通過引擎底層的事件機制,將對象行為與生命周期深度綁定。
魔術方法的用意:
- ? ? 解耦:將通用邏輯(如日志、驗證)從業務代碼中分離。
- ? ? 簡潔:用少量代碼實現常規需要多個方法才能完成的功能。
- ? ? 靈活:動態攔截對象操作,適應復雜業務場景的動態需求。