萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP ReflectionClass 反射類完整應用指南與實戰範例

什麼是 ReflectionClass?

ReflectionClass 是 PHP 內建的反射類,能在執行時動態獲取類的完整資訊(屬性、方法、常數、介面、父類、命名空間等),並支援動態實例化、呼叫方法、存取屬性等操作。它是框架開發、依賴注入容器、註解解析、單元測試等進階場景的核心基石。

基本用法:建立反射實例

<?php
namespace News;

class News {
    public $newsid;
    public function index() { /* ... */ }
}

// 一般實例化
$news = new News\News();

// 反射實例化(傳入「全限定類名」字串)
$ref = new \ReflectionClass('News\News');
// 或直接傳入物件
$ref = new \ReflectionClass($news);

常用資訊獲取方法

方法說明範例輸出
getName()完整類名(含命名空間)News\News
getShortName()不含命名空間的類名News
getNamespaceName()命名空間名稱News
getProperties()所有屬性(ReflectionProperty 陣列)含 public/protected/private
getMethods()所有方法(ReflectionMethod 陣列)可篩選 public/protected/private
getConstants()所有常數關聯陣列
getInterfaces()實作的介面ReflectionClass 陣列
getParentClass()父類反射物件ReflectionClass 或 false
isAbstract() / isInterface() / isTrait()類型判斷bool

實戰場景一:父類根據子類名稱動態載入配置

典型應用於「基礎 Controller」或「Model 基類」中,避免硬編碼子類名稱:

<?php
abstract class BaseController {
    protected $configs = [
        'UserController' => ['auth' => true, 'rate_limit' => 60],
        'ApiController'  => ['auth' => false, 'rate_limit' => 300],
    ];

    public function init() {
        $ref = new \ReflectionClass($this);          // $this 是子類實例
        $className = $ref->getShortName();           // 取得子類短名

        if (!isset($this->configs[$className])) {
            return true; // 無配置則跳過
        }

        $params = $this->configs[$className];
        return $this->handle($params);
    }

    abstract protected function handle(array $params);
}

實戰場景二:依賴注入容器自動解析建構子參數

<?php
class Container {
    public function make($className) {
        $ref = new \ReflectionClass($className);
        $constructor = $ref->getConstructor();

        if (!$constructor) {
            return $ref->newInstance();
        }

        $params = $constructor->getParameters();
        $dependencies = [];
        foreach ($params as $param) {
            $type = $param->getType();
            if ($type && !$type->isBuiltin()) {
                $dependencies[] = $this->make($type->getName()); // 遞歸解析
            } elseif ($param->isDefaultValueAvailable()) {
                $dependencies[] = $param->getDefaultValue();
            } else {
                throw new \Exception("無法解析參數: {$param->getName()}");
            }
        }
        return $ref->newInstanceArgs($dependencies);
    }
}

實戰場景三:註解解析(DocBlock 讀取)

<?php
/**
 * @Route("/user/{id}", methods={"GET"})
 * @Auth(roles={"admin","editor"})
 */
class UserController {}

$ref = new \ReflectionClass(UserController::class);
$docComment = $ref->getDocComment();
// 使用正則或 doctrine/annotations 解析 @Route、@Auth 等註解

注意事項與效能提醒

  • 反射涉及字串解析與內部結構遍歷,**效能較差**,避免在高頻熱點路徑(如大迴圈、每請求多次)大量使用。
  • 生產環境建議搭配 **快取機制**(如將反射結果序列化存入 Redis/檔案),下次直接讀取快取。
  • PHP 8.0+ 新增 ReflectionNamedType、ReflectionUnionType 等,型別提示更完整。

總結

ReflectionClass 賦予 PHP「運行時自我檢查」的能力,是現代框架(Laravel、Symfony、Hyperf 等)實現自動裝配、路由掃描、中介軟體解析等核心功能的關鍵。掌握反射 API,能讓你寫出更通用、更解耦、更具擴充性的程式碼。

copyright © 萬盛學電腦網 all rights reserved