Composer自动发现是Laravel 5.5引入的机制,通过解析包composer.json中extra.laravel.providers数组自动注册服务提供者,但不自动发布资源,需手动执行php artisan vendor:publish。

什么是 Composer 的自动发现(Package Discovery)
Composer 自动发现是 Laravel 5.5 引入的机制,让包在安装后无需手动执行 php artisan vendor:publish 或修改 config/app.php 就能自动注册服务提供者、发布配置/迁移/资源等。它不是 Composer 原生功能,而是 Laravel 框架层对 composer.json 中 extra.laravel.dont-discover 和 extra.laravel.providers 等字段的解析逻辑。
如何在包中启用自动发现
关键是在包的 composer.json 里正确声明 extra.laravel 配置。Laravel 安装该包时会扫描所有已安装包的 composer.json,提取 extra.laravel.providers 列表并自动注册对应服务提供者。
- 必须使用
extra.laravel.providers数组,值为完整类名字符串,例如:"extra": { "laravel": { "providers": ["Vendor\Package\ServiceProvider"] } } - 若需自动发布配置文件,同时添加
"aliases"或"dont-discover"控制粒度,但更常用的是配合publishes()方法在服务提供者中声明 - 不支持通配符或目录扫描,每个服务提供者必须显式列出
- 如果包同时支持 Laravel 和非 Laravel 环境,建议把服务提供者类放在
src/Providers/LaravelServiceProvider.php这类明确路径下,避免被误加载
为什么 php artisan vendor:publish 有时不生效
自动发现只负责服务提供者注册,不等于自动发布资源。很多开发者误以为启用了自动发现就不用手动 publish,结果配置文件没生成、迁移没复制、视图没导出——这是最常见的混淆点。
- 自动发现 ≠ 自动发布:发布动作仍需通过
php artisan vendor:publish --provider="Vendor\Package\ServiceProvider"触发 - 服务提供者中必须调用
$this->publishes(),且第一个参数是源路径数组(如__DIR__.'/../config/package.php' => config_path('package.php')),否则 publish 命令找不到内容 - 若在
composer.json中设置了"dont-discover": ["vendor/package"],则整个包都不会被扫描,服务提供者也不会注册 - Laravel 9+ 对
publishes()的路径校验更严格,源路径必须存在且可读,否则 publish 命令静默跳过
调试自动发现失败的典型方法
当包装好了却没反应,别急着重写服务提供者,先确认 Laravel 是否“看见”了它。
- 运行
composer show vendor/package,检查输出中是否包含laravel.providers字段及其值 - 执行
php artisan package:discover --ansi(Laravel 8+),它会强制重新扫描并打印所有被发现的提供者;若你的包不在列表里,说明composer.json配置有误或未被加载 - 检查包是否被
composer.json的autoload正确映射,尤其是 PSR-4 命名空间路径是否指向含服务提供者的目录 - 注意软链接开发场景:用
composer link或npm link类似方式本地开发包时,vendor/下实际是符号链接,某些旧版 Composer 可能跳过扫描,建议用composer install --no-dev后再测试
自动发现本身很简单,但它的生效依赖 Composer 加载顺序、Laravel 启动流程、路径权限和配置拼写——四个地方错一个,包就“隐身”。最常被忽略的是服务提供者类文件不存在或命名空间与 composer.json 不一致,连报错都没有,只有日志里一句“Provider not found”。











