PHP 反射 API(Reflection API)讓程式在執行期檢查、操作類別、介面、方法、屬性等結構,是框架開發、外掛系統、依賴注入容器的核心基石。本文透過一個「多頻道處理器」實例,展示如何利用 ReflectionClass 動態載入類別、獲取方法、實例化物件並呼叫目標方法。
假設系統支援多種通知頻道(Email、SMS、Push),每個頻道對應一個實作 exeRecd() 的類別。配置陣列 $chsMap 映射頻道代碼到類別名,執行時動態解析並調用:
foreach ($this->chs as $ch) {
$className = $this->chsMap[$ch]; // 如 'EmailHandler', 'SmsHandler'
if ($className) {
// 1. 獲取反射類別
$class = new ReflectionClass($className);
// 2. 獲取目標方法反射對象
$method = $class->getMethod('exeRecd');
// 3. 實例化物件(支援建構函數參數)
$instance = $class->newInstance($this->qq, $this->ip);
// 4. 呼叫方法並收集結果
$result[$ch] = $method->invoke($instance);
}
}
| 類別 | 常用方法 | 用途 |
|---|---|---|
ReflectionClass | newInstance(), newInstanceArgs(), getMethod(), getMethods(), getProperties(), getConstants(), implementsInterface() | 類別結構檢查與實例化 |
ReflectionMethod | invoke(), invokeArgs(), getParameters(), getReturnType(), isPublic(), isStatic() | 方法呼叫與簽名分析 |
ReflectionProperty | getValue(), setValue(), isPublic(), isProtected(), setAccessible(true) | 屬性讀寫(含私有) |
ReflectionParameter | getName(), getType(), isOptional(), getDefaultValue() | 參數資訊,支援依賴注入自動解析 |
newInstanceArgs($args) 可配合 ReflectionParameter::getType() 實現簡易 DI 容器。$prop->setAccessible(true) 後即可 getValue($obj)/setValue($obj, $val),測試與框架常用。ReflectionClass 實例(如靜態陣列或 APCu),避免重複解析同一類別。ReflectionException 會在類別/方法不存在時拋出,務必 try-catch 包裹。ReflectionNamedType, ReflectionUnionType 等新類別支援聯集型別、命名型別檢查。ReflectionAttribute (PHP 8) 讀取 #[Route], #[Inject] 等屬性。反射賦予 PHP「自我感知」能力,是框架級開發的必備技能。掌握 ReflectionClass::newInstanceArgs()、ReflectionMethod::invokeArgs()、setAccessible(true) 三大核心操作,即可應對 90% 的動態實例化與調用需求。記住:反射功能強大但有效能成本,生產環境務必緩存反射結果。