离线安装本地包必须用path仓库类型并禁用Packagist,否则composer require必联网校验包名和版本而失败;需配置本地仓库、全局关闭Packagist、用COMPOSER_DISABLE_NETWORK=1执行require@dev后update。

离线安装本地包,composer require 无效,必须用 path 仓库类型 + 显式禁用 Packagist,否则 Composer 仍会尝试联网查包名或 fallback 到官方源。
为什么 composer require 在离线时一定失败
它默认要访问 repo.packagist.org 校验包是否存在、版本是否合法、name 是否被注册——这个行为无法跳过,哪怕你本地目录里已有完整 composer.json。不设环境变量、不改仓库配置,require 命令根本不会读你硬盘上的文件。
-
composer require my/utils→ 离线必报Could not find package my/utils - 加
@dev(如my/utils:@dev)也无效,因为解析阶段就卡死了 - 试图用
--no-plugins --no-scripts无济于事,网络请求发生在更早的依赖解析环节
正确做法:用 path 类型仓库 + 全局禁用 packagist
这是唯一能绕过所有远程元数据请求的方式,前提是你的本地包目录结构干净、composer.json 合法。
- 本地包根目录必须有
composer.json,含完整"name"(如"acme/logger")和"version"或"branch-alias"字段 - 在项目根目录执行:
composer config repositories.local '{"type":"path","url":"./packages/acme-logger"}'(路径必须相对,不能是绝对路径) - 必须立刻运行:
composer config --global repo.packagist false,否则 Composer 仍会 fallback 查询官方源 - 确认项目级没残留配置:
composer config repo.packagist应输出空行
安装命令必须带 @dev,且不能用 update
composer install 不会触发本地包安装,只有 require 或 update 会拉取新包;但离线时 update 会连网校验,所以只能走 require 路径,并强制指定开发分支。
- 执行:
composer require acme/logger:@dev --no-update(先写入composer.json) - 再执行:
COMPOSER_DISABLE_NETWORK=1 composer update acme/logger --no-plugins --no-scripts - 关键点:
COMPOSER_DISABLE_NETWORK=1是硬开关,缺它update仍会访问packages.json - 不要用
--prefer-source,它会尝试git clone,离线必然失败
容易忽略的权限与路径陷阱
path 仓库依赖符号链接或真实复制,目标机若不支持 symlink(如某些 Windows 或容器环境),autoload 可能失效。
- 包目录路径必须可被项目 root 访问,比如
./packages/acme-logger,不能是/home/user/pkg - 确保
composer.json中"name"和require语句完全一致(大小写、斜杠方向都不能错) - 解压后检查
vendor/acme/logger是否为真实目录(不是 broken symlink),否则class_exists()会返回false - 如果目标机 PHP SAPI 是 FPM,测试 autoload 必须用相同 SAPI 运行:
php -r "require 'vendor/autoload.php'; var_dump(class_exists('Acme\Logger'));"
真正麻烦的不是命令怎么写,而是 composer.json 里一个拼错的 name、一条没删干净的 "repositories": [{"type": "packagist", "url": "https://packagist.org"}],都会让整个流程在离线时静默失败——建议用 composer install -v 看实际请求地址,而不是只盯着错误信息。


















