PHP 5.3+ 引入 __callStatic,配合既有的 __call,完整覆蓋實例與靜態方法的動態攔截。
| 方法 | 觸發條件 | 參數 |
|---|---|---|
__call($name, $arguments) | 呼叫**不可訪問的實例方法** (不存在、protected/private) | $name: 方法名 $arguments: 參數陣列 |
__callStatic($name, $arguments) | 呼叫**不可訪問的靜態方法** | 同上 |
<?php
class Member {
protected $data = [];
public function __call($func, $args) {
// 解析 set_xxx / get_xxx
$parts = explode('_', $func, 2);
if (count($parts) !== 2) return null;
[$type, $key] = $parts;
if (!in_array($type, ['set', 'get']) || $key === '') return null;
switch ($type) {
case 'set':
$this->data[$key] = $args[0] ?? null;
break;
case 'get':
return $this->data[$key] ?? null;
}
}
// 靜態版本同理
public static function __callStatic($func, $args) {
// 可實作靜態快取、單例存取等
}
}
class User extends Member {
public function show() {
foreach ($this->data as $k => $v) echo "$k: $v<br>";
}
}
class Profession extends Member {
public function show() {
foreach ($this->data as $k => $v) echo "$k: $v<br>";
}
}
// 使用
$user = new User();
$user->set_name('fdipzone');
$user->set_age(29);
$user->show(); // name: fdipzone / age: 29
$pro = new Profession();
$pro->set_profession('IT SERVICE');
$pro->set_price(2500);
$pro->show();
Model::__call 處理關聯)。$query->whereName('John')->orderByDate()->limit(10) 透過 __call 動態組合 SQL。User::createFromArray([...]) 由 __callStatic 解析並實例化。$client->getUsers() 自動對應 GET /users。__call / __callStatic 是 PHP 元編程的利器,賦予類別「方法不存在時的第二次機會」。善用於基礎設施層、適配器、建構器等穩定介面之上,能大幅提升開發體驗;濫用於業務核心則會犧牲可維護性。理解其觸發條件與參數結構,是駕馭動態特性的前提。