You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP包自动加载问题:get_declared_classes()未返回预期结果

问题描述

我正在开发一个PHP Composer包,它是带有Symfony命令的标准包,用于生成Avro文件。
在bin/avro文件中注册命令时,我添加了以下代码来加载自动加载文件:

require file_exists(__DIR__ . '/../vendor/autoload.php')
        ? __DIR__ . '/../vendor/autoload.php'
        : __DIR__ . '/../../../../vendor/autoload.php';

我以为这样就能自动加载包所在项目的所有文件,于是在一个空Laravel项目中执行了以下命令:

composer require lukecurtis93/avrogenerate
./vendor/bin/avro generate

但在包的DefaultAvroGenerator.php文件中,这段使用get_declared_classes()的代码:

// ...
$arr = [];
foreach (get_declared_classes() as $className) {
    if (in_array(Avroable::class, class_implements($className))) {
        $arr[] = $className;
    }
}
// ...

并没有返回Laravel应用中App/Models目录下的任何类(其他目录的类也无法获取)。

请问我哪里操作有误?这些类难道不应该通过get_declared_classes()获取到吗?是否需要为包进行额外配置?


解决方案

问题核心在于PHP自动加载机制和get_declared_classes()的特性:

  • get_declared_classes()仅返回已经被加载到内存中的类,而Composer的自动加载是延迟加载(懒加载)——只有当代码首次引用某个类时,才会触发文件加载。你的命令执行时,Laravel项目里的App/Models类没有被任何代码引用,自然不会被加载,也就不会出现在返回结果里。
  • 你当前的自动加载代码是正常的,但它只是让项目的自动加载器可用,并不会主动加载项目内的所有类。

要解决这个问题,推荐两种实用方案:

  1. 基于Composer规则扫描目标目录
    利用Composer的API读取项目的composer.json配置,获取PSR-4命名空间对应的目录(比如Laravel的App/对应App\命名空间),然后递归扫描这些目录下的文件,通过反射机制判断类是否实现了Avroable接口。这种方式不需要用户额外配置,符合PHP生态的自动加载规范。
  2. 让用户手动配置目标类
    提供配置文件(比如Laravel的config/avro-generate.php),让用户把需要生成Avro的类名列在配置中,你的包直接读取配置获取类名即可。这种方式更高效,也能避免不必要的目录扫描。

注意:不要尝试一次性加载项目所有类,这会严重拖慢命令执行速度,只加载你需要处理的目标类即可。

内容的提问来源于stack exchange,提问作者Luke Curtis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:35:48