PHP 的魔術方法 __call() 在物件導向開發中極具彈性,當呼叫不存在的方法時自動觸發,常用於動態代理、方法攔截、API 封裝等進階場景。本文透過實例詳細解析其運作機制與實戰應用。
<?php
class A {
public $name;
function test1($a) { echo "test1111"; }
function test2($a) { echo "test2222"; }
// 當呼叫不存在的方法時自動觸發
function __call($method, $args) {
echo "類別中找不到方法:" . $method;
echo "傳入參數:";
print_r($args);
}
}
$aaa = new A();
$aaa->test(1); // 呼叫不存在的 test() 方法
?>
類別中找不到方法:test 傳入參數:Array ( [0] => 1 )
<?php
class DatabaseProxy {
private $pdo;
private $table;
public function __construct(PDO $pdo, $table) {
$this->pdo = $pdo;
$this->table = $table;
}
public function __call($method, $args) {
// 支援 findById、findByEmail、findByUsername 等動態查詢
if (preg_match('/^findBy(.+)$/', $method, $matches)) {
$field = lcfirst($matches[1]); // 欄位名稱轉小駝峰
$value = $args[0];
$stmt = $this->pdo->prepare("SELECT * FROM {$this->table} WHERE {$field} = ?");
$stmt->execute([$value]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
throw new BadMethodCallException("方法 {$method} 不存在");
}
}
// 使用範例
$proxy = new DatabaseProxy($pdo, 'users');
$user = $proxy->findByEmail('test@example.com'); // 動態生成 SQL 查詢
?>
$client->getUsers() 自動映射至 GET /users__call 實現動態範圍查詢__call 透明化網路呼叫細節__call 僅攔截物件語境下的不可存取方法(不存在或權限不足)__callStatic()@method 標註提升 IDE 提示支援