| 魔術方法 | 觸發時機 | 鏈式操作中的角色 |
__call($name, $args) | 呼叫不存在的方法 | 攔截方法呼叫、執行邏輯、回傳 $this 實現鏈式 |
__toString() | 物件被當作字串輸出 | 輸出最終處理結果 |
完整實作範例:字串處理鏈
<?php
/**
* 鏈式操作基底類
*/
abstract class BaseChainObject {
private $_traceData = [];
protected $_methods = []; // 允許呼叫的方法白名單
public $data;
public function __construct($data) {
$this->data = $data;
$this->_traceData['__construct'] = $data;
}
// 物件轉字串時輸出最終結果
public function __toString() {
return (string)$this->data;
}
// 攔截不存在的方法呼叫
public function __call($name, $args) {
// 白名單驗證
if (!in_array($name, $this->_methods)) {
throw new Exception("不允許的方法: $name");
}
// 執行對應函式
$this->data = empty($args)
? call_user_func($name, $this->data)
: call_user_func_array($name, $args);
$this->_traceData[$name] = $this->data;
return $this; // 關鍵:回傳 $this 實現鏈式
}
// 除錯:追蹤處理過程
public function trace() {
var_dump($this->_traceData);
}
}
/**
* 字串處理鏈:僅允許 trim、strlen
*/
class StringChain extends BaseChainObject {
protected $_methods = ['trim', 'strlen'];
}
// 使用示範
$str = new StringChain(' ab rewqc ');
echo $str->trim()->strlen(); // 輸出: 8
$str->trace(); // 除錯輸出完整處理軌跡
?>
執行流程圖解
new StringChain(' ab rewqc ')
│
▼
$str->trim() ──▶ __call('trim', []) ──▶ trim(' ab rewqc ') = 'ab rewqc' ──▶ return $this
│
▼
->strlen() ──▶ __call('strlen', []) ──▶ strlen('ab rewqc') = 8 ──▶ return $this
│
▼
echo $str ──▶ __toString() ──▶ "8"
另一種實現方式:自定義方法回傳 $this
class FluentString {
private $str;
public function __construct($str) { $this->str = $str; }
public function trim() { $this->str = trim($this->str); return $this; }
public function upper() { $this->str = strtoupper($this->str); return $this; }
public function __toString() { return $this->str; }
}
echo (new FluentString(' hello '))->trim()->upper(); // "HELLO"
優缺點對比
| 方案 | 優點 | 缺點 |
魔術方法 __call | 動態支援任意函式、無需預先定義方法 | 效能稍低、IDE 無法提示、需白名單防禦 |
| 自定義方法 | 效能高、IDE 完美提示、型別安全 | 需手寫每個方法、擴展性弱 |
實務應用場景
- 查詢建構器(如 Laravel Query Builder)
- 集合/陣列流式處理(如 Laravel Collection)
- 驗證規則鏈、中介軟體管線
- HTML/表單建構器
總結
PHP 物件鏈式操作的本質是:__call 攔截動態呼叫 + 執行邏輯 + 回傳 $this + __toString 輸出結果。理解此原理,不僅能讀懂主流框架核心原始碼,更能設計出優雅的流暢介面 API。
- 上一篇文章: PhpStorm Terminal 無法輸入指令?Windows 10 相容性問題一鍵修復
- 下一篇文章: SAE 即時日誌介面 PHP SDK 完整實作:從官方 Python 版移植至 PHP
Copyright ©
程式碼之家 All Rights Reserved