下面给你一份清晰 + 可直接使用的讲解,完整说明
👉 PHP 中如何使用反射获取类的所有方法


一、什么是 PHP 反射(Reflection)?

反射允许你在运行时检查类、方法、属性、参数等结构信息,而不需要提前写死。

常见用途:

  • 框架自动注入(Laravel / Hyperf)
  • 注解 / Attribute 解析
  • AOP(切面)
  • 自动路由、自动文档
  • 单元测试、Mock

二、最基础:获取一个类的所有方法

示例 1:获取全部方法(包含父类)

class Demo {
    public function foo() {}
    protected function bar() {}
    private function baz() {}
}

$ref = new ReflectionClass(Demo::class);
$methods = $ref->getMethods();

foreach ($methods as $method) {
    echo $method->getName() . PHP_EOL;
}

📌 结果包含

  • public / protected / private
  • 父类方法

三、按可见性筛选方法(最常用)

只获取 public 方法

$methods = $ref->getMethods(ReflectionMethod::IS_PUBLIC);

foreach ($methods as $method) {
    echo $method->getName();
}

组合筛选(public + protected)

$methods = $ref->getMethods(
    ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
);


四、只获取“当前类”定义的方法(排除父类)

$methods = array_filter(
    $ref->getMethods(),
    fn($m) => $m->getDeclaringClass()->getName() === Demo::class
);

foreach ($methods as $method) {
    echo $method->getName() . PHP_EOL;
}


五、获取方法的详细信息(进阶)

foreach ($ref->getMethods() as $method) {
    echo "方法名: " . $method->getName() . PHP_EOL;
    echo "是否 public: " . $method->isPublic() . PHP_EOL;
    echo "是否 static: " . $method->isStatic() . PHP_EOL;
    echo "参数数量: " . $method->getNumberOfParameters() . PHP_EOL;
    echo "声明类: " . $method->getDeclaringClass()->getName() . PHP_EOL;
    echo "----------------" . PHP_EOL;
}


六、获取方法参数信息

$method = $ref->getMethod('foo');

foreach ($method->getParameters() as $param) {
    echo $param->getName();

    if ($param->hasType()) {
        echo ' : ' . $param->getType();
    }

    if ($param->isOptional()) {
        echo ' = ' . $param->getDefaultValue();
    }

    echo PHP_EOL;
}


七、获取注解 / Attribute(PHP 8+)

示例:Attribute 定义

#[Attribute]
class Route {
    public function __construct(public string $path) {}
}

使用反射读取

class Controller {
    #[Route('/user')]
    public function index() {}
}

$method = (new ReflectionClass(Controller::class))
            ->getMethod('index');

$attrs = $method->getAttributes(Route::class);

foreach ($attrs as $attr) {
    $instance = $attr->newInstance();
    echo $instance->path;
}


八、常见实战场景示例

1️⃣ 自动路由扫描

$controller = new ReflectionClass(UserController::class);

foreach ($controller->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
    if (! $method->isConstructor()) {
        echo "注册路由: " . $method->getName();
    }
}


2️⃣ 扫描可调用 API

$methods = array_filter(
    $ref->getMethods(ReflectionMethod::IS_PUBLIC),
    fn($m) => !str_starts_with($m->getName(), '__')
);


九、常见坑点(一定要看)

getMethods() 默认包含父类
❌ private 方法默认也会返回
❌ 反射比普通调用慢(但框架都会缓存)
❌ 匿名类 / Trait 行为不同


十、快速对照表

需求方法
所有方法getMethods()
public 方法IS_PUBLIC
当前类方法getDeclaringClass()
参数信息getParameters()
注解getAttributes()

十一、一句话总结

Reflection 是 PHP 框架的“显微镜”,能让代码在运行时看见自己