PHP 的魔術方法是在特定情境下自動被呼叫的特殊方法,名稱以雙底線開頭。本文將深入探討三個實用的魔術方法:__set_state、__clone 和 __autoload,透過程式碼範例說明其運作機制與應用場景。
var_export() 可將變數輸出為合法的 PHP 程式碼字串。自 PHP 5.1.0 起,若類別定義了靜態方法 __set_state(),則 var_export() 匯出物件時會產生呼叫此方法的程式碼,並將屬性陣列作為參數傳入。
<?php
class MyClass {
public $skill = 'php';
public static function __set_state(array $properties) {
$obj = new self();
foreach ($properties as $key => $value) {
$obj->$key = $value;
}
return $obj;
}
}
$instance = new MyClass();
$instance->age = 21;
// 匯出並重新建立物件
eval('$restored = ' . var_export($instance, true) . ';');
print_r($restored);
/* 輸出:
MyClass Object
(
[skill] => php
[age] => 21
)
*/
?>
此機制常用於快取、除錯或物件序列化場景。
PHP 5 中物件指派預設為參考傳遞。使用 clone 關鍵字可建立淺層複製,但巢狀物件屬性仍共享同一實例。透過實作 __clone() 可自訂深層複製邏輯。
<?php
class Address {
public $city = 'Taipei';
}
class User {
public $name = 'John';
public $address = null;
}
$user1 = new User();
$user1->address = new Address();
$user2 = clone $user1;
$user2->address->city = 'Kaohsiung';
echo $user1->address->city; // 輸出 Kaohsiung(原物件也被修改!)
?>
<?php
class User {
public $name = 'John';
public $address = null;
public function __clone() {
// 強制複製巢狀物件
$this->address = clone $this->address;
}
}
$user1 = new User();
$user1->address = new Address();
$user2 = clone $user1;
$user2->address->city = 'Kaohsiung';
echo $user1->address->city; // 輸出 Taipei(原物件不受影響)
?>
當實例化不存在的類別時,PHP 會嘗試呼叫 __autoload($className)。雖然 PHP 7.2 起已棄用,但理解其原理有助於掌握自動載入機制。
<?php
function __autoload($className) {
$file = "/home/project/classes/{$className}.php";
if (file_exists($file)) {
require_once $file;
} else {
die("Class {$className} Not Found");
}
}
// 若 MyClass 未定義,將自動載入 MyClass.php
$obj = new MyClass();
?>
現代最佳實踐:請使用 spl_autoload_register() 註冊多個自動載入器,符合 PSR-4 規範。
__set_state 讓 var_export() 完整支援物件還原__clone 解決巢狀物件深層複製需求__autoload 為早期自動載入方案,現已由 spl_autoload_register 取代善用魔術方法能讓物件導向程式更靈活、更符合直覺。