必须在主项目composer.json根级repositories中配置"type":"path"和相对路径url,且本地包name、version(如dev-main)与require严格一致,并运行composer dump-autoload确保autoload生效。

本地包必须用 repositories 声明 path 类型
Composer 不会自动扫描项目目录下的子文件夹找包,composer require mycompany/utils 这类命令默认只查 Packagist 或已配置的仓库。没声明 repositories,就等于没告诉 Composer “这个包就在本地”,它连看都不会看一眼。
正确做法是在项目根目录 composer.json 的最外层加一个 repositories 数组:
{
"repositories": [
{
"type": "path",
"url": "./packages/my-utils"
}
],
"require": {
"mycompany/utils": "dev-main"
}
}
-
url必须是相对路径(从composer.json所在位置算起),不能带file://,也不能用绝对路径(/home/xxx或C:\xxx在多数场景下静默失效) -
type必须是"path",写成"package"或漏掉整个repositories字段,都会导致composer require报 “Could not find package” - 本地包目录(如
./packages/my-utils)里必须有合法的composer.json,且其中name字段(如"mycompany/utils")要和require语句里写的完全一致(大小写敏感)
dev-main 版本号不是随便写的
本地包没有 Git 标签或发布版本时,Composer 默认按稳定性策略过滤掉 dev- 开头的版本——除非你显式允许。否则即使路径对、名字对,composer require mycompany/utils:dev-main 也会失败。
- 在项目
composer.json中加"minimum-stability": "dev"(全局放宽),或 - 在本地包自己的
composer.json中写明确的"version": "dev-main"(推荐,更可控) - 如果本地包是 Git 仓库,确保当前分支名就是
main或master;否则 Composer 会找不到对应分支
执行安装时必须带具体版本:composer require mycompany/utils:dev-main,不能省略 :dev-main。省略后 Composer 会去 Packagist 查最新稳定版,而不是走你配的本地路径。
装上了但 Class not found?先看 autoload 和 dump
成功 require 并不等于类能自动加载。90% 的 Class not found 错误和网络无关,而是 autoload 配置没生效。
- 确认本地包的
composer.json里有正确的autoload段,例如:"psr-4": {"MyCompany\Utils\": "src/"} - 运行
composer dump-autoload(开发阶段不用加-o),否则新注册的命名空间不会写入vendor/autoload.php - 别在
require 'vendor/autoload.php'之前就new MyCompanyUtilsHelper()——顺序错了,autoload 还没加载 - Laravel 用户注意:Facade、Service Provider 不是 Composer 自动注册的,得手动加进
config/app.php的providers或aliases
离线调试时最易忽略的 Windows 路径陷阱
Windows 下 path 类型仓库行为和 Linux/macOS 不一致,尤其容易卡在 symlink 和路径分隔符上。
- 路径写成
"./packages/my-utils"没问题,但写成".packagesmy-utils"(反斜杠)可能被跳过——Composer 内部路径处理依赖 Unix 风格 - 如果本地包里用了
post-install-cmd脚本生成符号链接(比如 Laravel 的storage:link),Windows 默认不支持,会导致安装卡住或失败 - 建议开发期统一用 WSL2 或 Docker Desktop 的 Linux 容器跑
composer install,避免因平台差异掩盖真实问题
真正麻烦的从来不是“怎么让包装上”,而是“怎么让装上的包在目标环境里跑起来”。路径、autoload、版本对齐、平台行为——四个点只要漏一个,Class not found 就会准时出现,而且错误信息里根本不会提是哪一环断了。











