| 類別 | 用途 |
|---|---|
| ReflectionClass | 類/介面/Trait 結構分析 |
| ReflectionMethod | 方法資訊與動態調用 |
| ReflectionProperty | 屬性資訊與動態存取 |
| ReflectionParameter | 方法參數型別、預設值、位置 |
| ReflectionFunction | 函數/閉包分析 |
| ReflectionExtension | 擴充模組資訊 |
根據設定檔動態建立模組實例,並自動注入建構子/Setter 依賴。
interface Module { public function execute(); }
class FtpModule implements Module {
public function setHost($host) { echo "FTP Host: $host\n"; }
public function setUser($user) { echo "FTP User: $user\n"; }
public function execute() { /* ... */ }
}
class PersonModule implements Module {
public function setPerson(Person $person) { echo "Person: {$person->name}\n"; }
public function execute() { /* ... */ }
}
class Person { public $name; public function __construct($name) { $this->name = $name; } }
class ModuleRunner {
private $configData = [
'PersonModule' => ['person' => 'bob'],
'FtpModule' => ['host' => 'example.com', 'user' => 'anon'],
];
private $modules = [];
public function init() {
$interface = new ReflectionClass('Module');
foreach ($this->configData as $moduleName => $params) {
$moduleClass = new ReflectionClass($moduleName);
// 1. 驗證型別相容性
if (!$moduleClass->isSubclassOf($interface)) {
throw new Exception("模組 $moduleName 不實作 Module 介面");
}
// 2. 實例化(無參建構子)
$module = $moduleClass->newInstance();
// 3. 掃描所有 public 方法尋找 Setter
foreach ($moduleClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
$this->handleMethod($module, $method, $params);
}
$this->modules[] = $module;
}
}
private function handleMethod($module, ReflectionMethod $method, array $params) {
$name = $method->getName();
$args = $method->getParameters();
// 僅處理 setXxx() 單參數方法
if (count($args) !== 1 || strncasecmp($name, 'set', 3) !== 0) return;
$prop = strtolower(substr($name, 3)); // setHost -> host
if (!isset($params[$prop])) return;
$arg = $args[0];
$typeClass = $arg->getClass(); // 取得型別宣告的類
if ($typeClass === null) {
// 純量型別直接注入
$method->invoke($module, $params[$prop]);
} else {
// 物件型別:遞迴建構實例
$method->invoke($module, $typeClass->newInstance($params[$prop]));
}
}
}
$runner = new ModuleRunner();
$runner->init();
適用於代碼生成器、文件產生器、熱重載偵測等場景。
class ReflectionUtil {
public static function getClassSource(ReflectionClass $class): string {
$path = $class->getFileName();
$lines = file($path);
$start = $class->getStartLine() - 1; // 0-based
$length = $class->getEndLine() - $class->getStartLine() + 1;
return implode(array_slice($lines, $start, $length));
}
}
// 使用範例
$className = 'Person';
$path = "../practice/{$className}.php";
if (!file_exists($path) || !class_exists($className)) {
throw new Exception("類別不存在");
}
echo ReflectionUtil::getClassSource(new ReflectionClass($className));
$class = new ReflectionClass('SomeClass');
$prop = $class->getProperty('privateProp');
$prop->setAccessible(true); // 關鍵:繞過可見性限制
$value = $prop->getValue($instance);
$class = new ReflectionClass('DbConnection');
$instance = $class->newInstanceArgs(['host' => 'localhost', 'port' => 3306]);
$method = new ReflectionClass('UserService')->getMethod('login');
$docComment = $method->getDocComment(); // 取得 /** ... */ 內容
// 配合 doctrine/annotations 解析 @Route、@Entity 等屬性
ReflectionClass 實例、方法參數陣列)new $className(...$args) 而非 ReflectionClass::newInstanceArgs()