運行時動態獲取類結構信息、實例化對象、調用方法、訪問/修改屬性、讀取註釋,支撐框架級開發:依賴注入、ORM 映射、路由分發、自動文檔生成、插件系統。
hasMethod()/hasProperty() 存在性檢查;newInstanceArgs() 動態構造(替代 new Class(...));getDocComment() 讀取類/屬性/方法級文檔註釋。<?php
$class = new ReflectionClass('Person'); // 1. 建立反射類
$instance = $class->newInstanceArgs($args); // 2. 動態實例化(等同 new Person(...$args))
$properties = $class->getProperties(); // 所有屬性 $privateProps = $class->getProperties(ReflectionProperty::IS_PRIVATE); // 僅私有 // 可見性常量 ReflectionProperty::IS_STATIC ReflectionProperty::IS_PUBLIC ReflectionProperty::IS_PROTECTED ReflectionProperty::IS_PRIVATE // 組合用法:IS_PUBLIC | IS_PROTECTED
foreach ($properties as $prop) {
if ($prop->isProtected()) {
$doc = $prop->getDocComment();
preg_match('/type\=([a-z_]+)/', $doc, $matches);
echo "Column type: {$matches[1]}\n"; // primary_autoincrement, varchar, text
}
}
// 獲取所有方法
$methods = $class->getMethods(); // 返回 ReflectionMethod[]
// 存在性檢查
if ($class->hasMethod('getName')) { ... }
// 獲取單一方法
$method = $class->getMethod('getName');
// 三種調用方式
$instance->getName(); // 1. 原生調用
$class->getMethod('getName')->invoke($instance); // 2. 反射調用無參
$class->getMethod('setName')->invokeArgs($instance, ['snsgou.com']); // 3. 反射調用帶參數組
| 能力 | 方法/屬性 |
|---|---|
| 可見性判斷 | isPublic(), isProtected(), isPrivate(), isStatic() |
| 參數信息 | getNumberOfParameters(), getParameters() (返回 ReflectionParameter[]) |
| 返回類型 (PHP 7+) | getReturnType() |
| 聲明類 | getDeclaringClass() |
| 動態調用 | invoke($obj, ...$args), invokeArgs($obj, $argsArray) |
$method = new ReflectionMethod('Person', 'test'); // 直接綁定類+方法名
if ($method->isPublic() && !$method->isStatic()) {
echo 'Action 符合要求:public 非靜態';
}
echo "參數個數: " . $method->getNumberOfParameters();
$params = $method->getParameters();
foreach ($params as $p) {
echo " - {$p->getName()} (可選: " . ($p->isOptional() ? '是' : '否') . ")";
}
// 掃描目錄下所有類,檢測是否實現 PluginInterface
$plugins = [];
foreach (glob('plugins/*.php') as $file) {
require_once $file;
$className = basename($file, '.php');
if (!class_exists($className)) continue;
$rc = new ReflectionClass($className);
if ($rc->implementsInterface('PluginInterface') && !$rc->isAbstract()) {
$plugins[] = $rc->newInstanceArgs([$container]);
}
}