首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 魔術方法完整匯總:從 __construct 到 __debugInfo 15 大魔術方法詳解

     編輯:PHP 綜合知識

什麼是魔術方法?

PHP 將所有以雙底線 __ 開頭的方法視為魔術方法,它們在特定時機自動被呼叫,實現「重載」與物件生命週期攔截。自訂方法不可使用 __ 開頭。

15 大魔術方法分類總覽

物件生命週期

方法觸發時機備註
__construct()實例化物件時初始化資源、注入依賴
__destruct()物件銷毀/腳本結束釋放資源、關閉連線、不可拋出異常
__clone()clone $obj 完成後調整複製行為、防止單例被複製

屬性重載 (Property Overloading)

方法觸發條件參數
__get($name)讀取不可存取/不存在屬性$name: 屬性名
__set($name, $value)寫入不可存取/不存在屬性$name, $value
__isset($name)isset()/empty() 檢查不可存取屬性$name
__unset($name)unset() 不可存取屬性$name

限制:不可宣告為 static,PHP 5.3+ 會發出警告。

方法重載 (Method Overloading)

方法觸發條件參數
__call($name, $args)呼叫不可存取/不存在實例方法$name: 方法名, $args: 參數陣列
__callStatic($name, $args)靜態呼叫不可存取/不存在靜態方法$name, $args (PHP 5.3+)

序列化控制

方法觸發時機回傳值/用途
__sleep()serialize() 前回傳需序列化屬性名陣列;回傳 null 會產生 notice
__wakeup()unserialize() 後重建資源連線、初始化狀態

類型轉換與呼叫

方法觸發時機限制
__toString()物件當字串使用 (echo/print)必須回傳字串;不可拋出異常 (PHP 5.2+ 支援 printf %s)
__invoke($args...)物件當函數呼叫 $obj()PHP 5.3+;配合 is_callable() 判斷

匯出與除錯

方法觸發時機備註
__set_state($arr)var_export() 匯出類別靜態方法;回傳值作為匯出結果 (PHP 5.1+)
__debugInfo()var_dump() 輸出物件回傳陣列控制顯示屬性 (PHP 5.6+)

完整實作範例

<?php
class MagicDemo {
    protected $data = [];

    // 生命週期
    public function __construct() {
        echo __METHOD__ . " 實例化物件\n";
    }
    public function __destruct() {
        echo __METHOD__ . " 銷毀物件\n";
    }
    public function __clone() {
        echo __METHOD__ . " 複製物件\n";
    }

    // 屬性重載
    public function __set($name, $value) {
        $this->data[$name] = $value;
        echo __METHOD__ . " 設定 {$name} = {$value}\n";
    }
    public function __get($name) {
        echo __METHOD__ . " 讀取 {$name}\n";
        return isset($this->data[$name]) ? $this->data[$name] : null;
    }
    public function __isset($name) {
        echo __METHOD__ . " 檢查 {$name}\n";
        return isset($this->data[$name]);
    }
    public function __unset($name) {
        echo __METHOD__ . " 刪除 {$name}\n";
        unset($this->data[$name]);
    }

    // 方法重載
    public function __call($name, $args) {
        echo __METHOD__ . " 呼叫方法 {$name} 參數: " . implode(', ', $args) . "\n";
        return "magic method\n";
    }
    public static function __callStatic($name, $args) {
        echo __METHOD__ . " 靜態呼叫 {$name} 參數: " . implode(', ', $args) . "\n";
        return "magic static\n";
    }

    // 序列化
    public function __sleep() {
        echo __METHOD__ . " 準備序列化\n";
        return array_keys($this->data);
    }
    public function __wakeup() {
        echo __METHOD__ . " 反序列化完成\n";
    }

    // 類型轉換
    public function __toString() {
        return __CLASS__ . "\n";
    }
    public function __invoke($arg) {
        echo __METHOD__ . " 當函數呼叫,參數: {$arg}\n";
        return __METHOD__ . "\n";
    }

    // 匯出/除錯
    public static function __set_state($arr) {
        echo __METHOD__ . " var_export 匯出\n";
        $obj = new self();
        $obj->data = $arr;
        return $obj;
    }
    public function __debugInfo() {
        echo __METHOD__ . " var_dump 除資訊\n";
        return ['data' => 'from __debugInfo'];
    }
}

// 測試所有魔術方法
$obj = new MagicDemo();                    // __construct
$obj->title = "hello";                     // __set
echo $obj->title;                          // __get
$obj->test("a", "b", "c");                 // __call
MagicDemo::staticMethod("x", "y");         // __callStatic
var_dump(isset($obj->aaa));                // __isset
unset($obj->aaa);                          // __unset
$serialized = serialize($obj);             // __sleep
unserialize($serialized);                  // __wakeup
echo $obj;                                 // __toString
$obj("invoke test");                       // __invoke
$obj2 = clone $obj;                        // __clone
eval('$obj3 = ' . var_export($obj, true) . ';'); // __set_state
var_dump($obj);                            // __debugInfo

魔術常數補充

隨程式碼位置變化的 8 個常數:

常數含義
__LINE__當前行號
__FILE__完整檔案路徑
__DIR__檔案所在目錄
__FUNCTION__函數名稱
__CLASS__類別名稱
__TRAIT__Trait 名稱
__METHOD__類別方法名
__NAMESPACE__命名空間名稱

常用於除錯日誌、動態載入、錯誤追蹤。

最佳實踐建議

  1. 慎用重載:__get/__set/__call 會降低程式碼可讀性與 IDE 提示支援,必要時才使用
  2. 序列化安全:__sleep 排除敏感資源 (資料庫連線、檔案控制代碼)
  3. 單例防複製:__clone 中拋出異常或觸發錯誤
  4. 除資訊控制:__debugInfo 隱藏敏感屬性 (密碼、Token)
  5. __destruct 中不可拋出異常,會導致 Fatal Error
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved