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

PHP 常用魔術方法速查表:觸發條件、返回值規範與實戰代碼片段

     編輯:PHP 相關知識

PHP 常用魔術方法速查表:觸發條件、返回值規範與實戰代碼片段

魔術方法以 __ 開頭,在特定操作時自動觸發。本文整理 13 個核心魔術方法的觸發條件、參數、返回值規範,提供最小可用代碼片段,作為開發時的快速參考卡片。

生命周期類

方法觸發條件參數返回值代碼片段
__constructnew Class()任意voidpublic function __construct(private Db $db) {}
__destruct對象銷毀 (引用歸零/腳本結束)無voidpublic function __destruct() { $this->db->close(); }
__cloneclone $obj 後無voidpublic function __clone() { $this->id = Uuid::v4(); }

屬性重載類

方法觸發條件參數返回值代碼片段
__get讀取不可訪問屬性 $obj->propstring $namemixedpublic function __get($n) { return $this->data[$n] ?? null; }
__set寫入不可訪問屬性 $obj->prop = $vstring $name, mixed $valuevoidpublic function __set($n, $v) { $this->data[$n] = $v; }
__issetisset($obj->prop) / empty()string $nameboolpublic function __isset($n) { return isset($this->data[$n]); }
__unsetunset($obj->prop)string $namevoidpublic function __unset($n) { unset($this->data[$n]); }

方法重載類

方法觸發條件參數返回值代碼片段
__call調用不可訪問實例方法 $obj->method()string $name, array $argsmixedpublic function __call($m, $a) { return $this->proxy->$m(...$a); }
__callStatic調用不可訪問靜態方法 Class::method()string $name, array $argsmixedpublic static function __callStatic($m, $a) { return self::$factory->$m(...$a); }

序列化類

方法觸發條件參數返回值代碼片段
__sleepserialize($obj) 前無array (屬性名)public function __sleep() { return ['data', 'config']; }
__wakeupunserialize($str) 後無voidpublic function __wakeup() { $this->reconnect(); }
__serializeserialize($obj) (7.4+)無array (鍵值對)public function __serialize() { return ['v'=>2, 'data'=>$this->data]; }
__unserializeunserialize($str) (7.4+)array $datavoidpublic function __unserialize($d) { $this->data=$d['data']; }

轉換與調試類

方法觸發條件參數返回值代碼片段
__toString對象作字符串 echo $obj無stringpublic function __toString() { return $this->name; }
__invoke對象作函數 $obj()任意mixedpublic function __invoke($x) { return $this->fn($x); }
__set_statevar_export($obj) (靜態)array $propsobjectpublic static function __set_state($p) { return new self($p); }
__debugInfovar_dump($obj) (5.6+)無arraypublic function __debugInfo() { return ['id'=>$this->id, 'secret'=>'***']; }

完整演示類

class MagicDemo {
    private $data = [];
    private $resource;

    // 構造/析構
    public function __construct() {
        $this->resource = fopen('php://memory', 'r+');
        echo "__construct\n";
    }
    public function __destruct() {
        fclose($this->resource);
        echo "__destruct\n";
    }

    // 屬性重載
    public function __get(string $name) {
        echo "__get($name)\n";
        return $this->data[$name] ?? null;
    }
    public function __set(string $name, $value) {
        echo "__set($name, $value)\n";
        $this->data[$name] = $value;
    }
    public function __isset(string $name): bool {
        echo "__isset($name)\n";
        return isset($this->data[$name]);
    }
    public function __unset(string $name) {
        echo "__unset($name)\n";
        unset($this->data[$name]);
    }

    // 方法重載
    public function __call(string $name, array $args) {
        echo "__call($name, " . json_encode($args) . ")\n";
        return "called $name";
    }
    public static function __callStatic(string $name, array $args) {
        echo "__callStatic($name, " . json_encode($args) . ")\n";
        return "static $name";
    }

    // 序列化 (新協議)
    public function __serialize(): array {
        echo "__serialize\n";
        return ['data' => $this->data, 'version' => 1];
    }
    public function __unserialize(array $data): void {
        echo "__unserialize\n";
        $this->data = $data['data'] ?? [];
    }

    // 舊協議 (兼容)
    public function __sleep(): array {
        echo "__sleep\n";
        return ['data'];
    }
    public function __wakeup(): void {
        echo "__wakeup\n";
        $this->resource = fopen('php://memory', 'r+');
    }

    // 轉換/調試
    public function __toString(): string {
        return "MagicDemo(data=" . count($this->data) . ")";
    }
    public function __invoke(string $action) {
        return "invoked: $action";
    }
    public static function __set_state(array $props): self {
        $obj = new self();
        $obj->data = $props['data'] ?? [];
        return $obj;
    }
    public function __debugInfo(): array {
        return ['data_keys' => array_keys($this->data), 'resource' => '***'];
    }
    public function __clone() {
        echo "__clone\n";
        $this->resource = fopen('php://memory', 'r+');
    }
}

// 測試腳本
$obj = new MagicDemo();
$obj->name = 'test';           // __set
echo $obj->name;               // __get
isset($obj->name);             // __isset
unset($obj->name);             // __unset
$obj->unknownMethod(1, 2);     // __call
MagicDemo::staticMethod();     // __callStatic
$serialized = serialize($obj); // __serialize -> __sleep
unserialize($serialized);      // __unserialize -> __wakeup
echo $obj;                     // __toString
$obj('action');                // __invoke
eval('$obj2 = ' . var_export($obj, true) . ';'); // __set_state
var_dump($obj);                // __debugInfo
$cloned = clone $obj;          // __clone

關鍵規範總結

  1. 不可 static 聲明:__get/__set/__isset/__unset/__call 必須為實例方法,PHP 5.3+ 靜態聲明拋出 E_DEPRECATED。
  2. __toString 必須返回字符串:拋出異常或返回非字符串觸發 E_RECOVERABLE_ERROR 並終止。
  3. __sleep 返回非數組:導致 serialize() 返回 null 並 E_NOTICE。
  4. __wakeup 安全風險:反序列化可實例化任意類,必須配合 allowed_classes 白名單。
  5. 遞歸陷阱:__get 中訪問 $this->prop 會再次觸發 __get,內部用 $this->data['prop']。
  6. 繼承調用:子類覆蓋時通常需 parent::__construct()、parent::__destruct()、parent::__clone()。

魔術常量速查

__LINE__     // 當前行號 (int)
__FILE__     // 文件完整路徑 (string)
__DIR__      // 文件目錄 (string, 等同 dirname(__FILE__))
__FUNCTION__ // 函數名 (string)
__CLASS__    // 類名含命名空間 (string)
__TRAIT__    // Trait 名 (string)
__METHOD__   // 類方法名 (string)
__NAMESPACE__// 當前命名空間 (string)

將此頁面加入書籤,開發遇到魔術方法即查即用,避免踩坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved