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

PHP 5 魔術方法完整指南:13 個魔術方法與 5 個魔術常數深度解析

     編輯:PHP 相關知識

什麼是魔術方法?

以雙底線 __ 開頭的特殊方法,PHP 在特定時機自動呼叫,無需手動調用,賦予物件「魔術」行為。

13 大魔術方法詳細解析

方法觸發時機參數回傳值要求典型用途
__construct()實例化物件時任意無初始化屬性、資源連線
__destruct()物件銷毀時(腳本結束/unset)無無釋放資源、關閉連線、寫入日誌
__call($name, $args)呼叫不存在的實例方法$name: 方法名
$args: 參數陣列
任意動態方法代理、API 客戶端
__callStatic($name, $args)呼叫不存在的靜態方法$name: 方法名
$args: 參數陣列
任意靜態工廠、動態查詢建構
__get($name)讀取不可存取屬性時$name: 屬性名屬性值虛擬屬性、延遲載入、資料轉換
__set($name, $value)寫入不可存取屬性時$name: 屬性名
$value: 值
無資料驗證、自動轉換、觸發事件
__isset($name)對不可存取屬性呼叫 isset()/empty()$name: 屬性名bool虛擬屬性存在性檢查
__unset($name)對不可存取屬性呼叫 unset()$name: 屬性名無清理虛擬屬性、快取失效
__toString()物件當作字串使用時無必須回傳字串物件字串表示、除錯輸出
__invoke()物件當作函數呼叫時任意任意可呼叫物件、閉包替代、策略模式
__clone()物件被 clone 關鍵字複製時無無深度複製、重置識別碼、複製資源
__sleep()serialize() 序列化前無陣列:屬性名列表排除資源連線、壓縮大型資料
__wakeup()unserialize() 反序列化後無無重建資源連線、初始化狀態
__set_state($arr)var_export() 匯出時$arr: 屬性陣列物件實例自定義匯出格式、單例模式支援
__autoload($class)實例化不存在類別時 (已棄用)$class: 類別名無自動載入類別檔案

重點方法實戰範例

__toString():物件字串化

class Person {
    private $name, $age;
    public function __construct($name, $age) {
        $this->name = $name; $this->age = $age;
    }
    public function __toString() {
        return "Person: {$this->name}, {$this->age} 歲";
    }
}
$p = new Person("小明", 20);
echo $p; // 輸出: Person: 小明, 20 歲

__clone():深度複製控制

class Person {
    public $name;
    public $tags = [];
    public function __clone() {
        $this->name = "副本_" . $this->name;
        $this->tags = []; // 重置標籤,避免共用陣列引用
    }
}
$p1 = new Person("原始");
$p1->tags[] = "tag1";
$p2 = clone $p1;
echo $p2->name; // 副本_原始
print_r($p2->tags); // Array() - 獨立陣列

__call():動態方法代理

class APIClient {
    private $baseUrl;
    public function __call($method, $args) {
        $endpoint = "/api/" . strtolower($method);
        return $this->request($endpoint, $args[0] ?? []);
    }
    private function request($endpoint, $data) { /* HTTP 請求邏輯 */ }
}

$client = new APIClient();
$client->getUser(['id' => 1]);      // 實際呼叫 request('/api/getuser', ...)
$client->createOrder(['item' => 'A']); // 實際呼叫 request('/api/createorder', ...)

__sleep()/__wakeup():序列化控制

class UserSession {
    public $userId;
    public $permissions = [];
    private $dbConnection; // PDO 實例,不可序列化
    
    public function __sleep() {
        return ['userId', 'permissions']; // 僅序列化這兩個屬性
    }
    
    public function __wakeup() {
        $this->dbConnection = new PDO(...); // 反序列化後重建連線
    }
}

5 大魔術常數

常數說明範例輸出
__LINE__當前行號25
__FILE__完整檔案路徑(含檔名)/var/www/html/index.php
__DIR__當前檔案目錄路徑/var/www/html
__FUNCTION__函數名稱(區分大小寫,PHP 5+)myFunction
__CLASS__類別名稱(含命名空間,區分大小寫)App\Models\User
__METHOD__類別方法名稱App\Models\User::getName
__NAMESPACE__當前命名空間App\Models

進階:__autoload vs spl_autoload_register

__autoload() 已棄用 (PHP 7.2) / 移除 (PHP 8.0),僅能定義一個載入函數。

spl_autoload_register() 支援多載入器堆疊,符合 PSR-4 規範,為現代標準做法。

// 現代自動載入寫法
spl_autoload_register(function ($class) {
    $file = __DIR__ . '/src/' . str_replace('\\', '/', $class) . '.php';
    if (file_exists($file)) require $file;
});

常見陷阱與注意事項

  • __toString() 必須回傳字串,否則拋出 E_RECOVERABLE_ERROR
  • __sleep() 回傳陣列必須為屬性名字串,否則該屬性不會被序列化
  • __call() 僅攔截不可存取的方法(不存在或權限不足)
  • 魔術方法不能被靜態呼叫(除 __callStatic/__set_state)
  • 繼承關係中,子類別可覆寫父類別魔術方法
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved