隐式依赖指代码未显式声明(如use、new、composer.json),但运行时通过配置类名、di容器反射、模板调用、autoload副作用或php扩展等方式触发加载的依赖。

没有可靠方式能全自动检测隐式依赖——它本质是运行时行为,静态工具只能覆盖有限场景。
什么是隐式依赖?
隐式依赖指代码里没写 use、没直接 new、也没在 composer.json 中声明,但实际运行时靠以下机制触发加载的包:
- 配置文件里写死的类名字符串(如
monolog.handler.stream_handler) - DI 容器通过反射或字符串注册的服务(
$container->get('cache.adapter.redis')) - 模板引擎中调用的类(Blade/Twig 里的
@include或{{ AppHelpersStr::slug() }}) - Composer 的
autoload或autoload-dev自动加载规则触发的副作用(如symfony/polyfill-mbstring注册函数别名) - PHP 扩展级绑定(
ext-redis被某包在require里声明,但你代码里只用new Redis())
composer-unused 为什么对隐式依赖基本失效
composer-unused 只扫描 PHP 源码中的 use、new、class_exists、interface_exists 等显式符号,不解析:
- 字符串拼接类名:
$class = 'Monolog\Handler\' . $type . 'Handler'; new $class; - YAML/JSON 配置里的类引用:
handler: MonologHandlerStreamHandler - Blade 模板中的
@php块或{{ }}内部调用 - 被
provide声明替代的包(如psr/log被monolog/monolog提供,但你代码里只用LoggerInterface)
它默认跳过 tests/、config/、resources/ 目录,而这些恰恰是隐式引用高发区。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
人工验证隐式依赖的可行路径
必须结合运行时观察和配置审查,不能只靠静态扫描:
- 启动应用后访问所有关键路径,检查日志是否报
Class not found—— 这是最直接的信号 - 临时删掉一个疑似“未使用”的包,再跑完整测试套件 + 手动冒烟测试,看是否崩溃
- 检查
composer.json的autoload和autoload-dev是否包含非标准目录(如"app/Providers"),这些路径下的类可能被自动加载但未被composer-unused扫到 - 搜索配置文件:
grep -r "Monolog\\Handler" config/ resources/ --include="*.php" --include="*.yml" --include="*.yaml" - 检查 DI 容器绑定定义(Laravel 的
AppServiceProvider、Symfony 的services.yaml)里是否有字符串类名
最容易被忽略的点:autoload 触发的副作用
有些包根本没被你的代码调用,但只要 Composer 加载了它的 autoloader,就会执行全局副作用。比如:
-
symfony/polyfill-*包会在bootstrap.php中注册函数别名(mb_strlen等),删掉会导致运行时报错 -
laravel/tinker在vendor/laravel/tinker/src/Console/TinkerCommand.php中注册了 Artisan 命令,即使你从不运行php artisan tinker,删掉它也会让命令注册失败 -
doctrine/annotations会注册注解读取器,哪怕你项目里一个@Route都没写,只要框架加载了它的 autoloader,就可能被间接依赖
这类依赖无法通过代码扫描发现,只能靠删除后实测,或查 vendor/composer/autoload_*.php 文件确认哪些包的 autoloader 被实际引入。










