composer create-project在离线机上一定失败,因其本质是远程克隆模板仓库并递归执行install,必须联网获取packages.json元数据,不读缓存、不认本地vendor,且COMPOSER_DISABLE_NETWORK=1对其无效。

离线部署 ThinkPHP 框架,不能靠 composer install 现场拉包,必须提前在联网机完成全量构建并验证,再整体迁移——否则 99% 的失败都卡在“以为离线了,其实还在悄悄连 packagist.org”。
为什么 composer create-project 在离线机上一定失败
这个命令本质是远程克隆模板仓库 + 递归 install 依赖,离线时会直接卡在 Could not fetch https://repo.packagist.org/packages.json。它不读缓存、不认本地 vendor、也不支持 --offline 参数。哪怕你把 composer.phar 拷过去,只要没提前准备好完整元数据,就起不来。
- 报错典型形式:
Failed to download topthink/think: file could not be downloaded (HTTP 404)或Package topthink/framework not found - 即使加了
COMPOSER_DISABLE_NETWORK=1,create-project仍会尝试解析远程仓库索引,该变量只影响后续install阶段 - TP5 和 TP6/8 的模板包(
topthink/think)结构不同,离线时若混用源机环境(如 PHP 8.2 装 TP8),目标机 PHP 7.4 就会因语法错误直接退出
composer install --no-plugins --no-scripts --no-autoloader 是唯一可信赖的离线命令
它不做任何写操作,只做三件事:比对 composer.lock 里的每个包路径、版本、dist.shasum,和当前 vendor/ 目录下实际文件是否完全一致。有差异就报错,没差异就静默退出——这才是真正“校验型”离线行为。
- 必须确保
vendor/和composer.lock来自同一台联网机、同一轮composer install --no-dev --optimize-autoloader构建 - 执行前先检查:
ls -la vendor/ | head -15看是否有明显缺失目录;git status composer.lock vendor/确认未被手动修改 - 如果输出里出现
Loading from cache,说明 Composer 还在查全局缓存——这不是你想要的,应先清空或临时禁用:composer config --global cache-dir /dev/null - 加
--dry-run(Composer ≥ 2.5)可预览行为,避免误覆盖已有 vendor
TP5 离线部署必须用 topthink/framework:^5.1 + topthink/think 骨架组合
直接 require topthink/think 只装进 vendor,不会生成 public/、app/、think 命令脚本——框架根本跑不起来。TP5 正确离线路径是:联网机用骨架初始化 → 锁定 framework 版本 → 打包整个项目目录。
- 联网机操作顺序:
composer create-project topthink/think tp5 --prefer-dist -n→ 进入tp5/后确认composer.json中"topthink/framework"版本为^5.1;若为^6.0,立刻删掉vendor和composer.lock,再运行composer require topthink/framework:^5.1 --update-with-dependencies - 验证是否真离线可用:
php -r "require 'vendor/autoload.php'; echo class_exists('think\App') ? 'TP5 OK' : 'FAIL';" - 打包时必须包含:
composer.lock、vendor/、public/、app/、think文件(Linux/macOS 注意权限,Windows 注意换行符) - 离线机部署后第一件事不是改代码,而是跑
php think run或php -S localhost:8000 -t public/,看首页能否加载;若报require(): open_basedir restriction,检查public/index.php中APP_PATH是否指向../app/(TP5.1 默认路径)
复制 vendor/ 比任何命令都可靠,但环境一致性是硬门槛
只要源机和目标机的 PHP 小版本(如 7.4.33 vs 7.4.30)、关键扩展(mbstring、openssl、zlib)、甚至 opcache.enable_cli 设置一致,vendor/ 就是可执行资产,不是中间产物。
- 最常被忽略的点:
composer --version不一致会导致installed.json格式解析失败,表现为Class not found却无任何报错日志 - 别信“差不多就行”:PHP 8.0 和 8.1 的
match表达式 ABI 不同,哪怕只是vendor/topthink/framework里一行语法,也会让整个 autoload 失效 - 上线前最小验证脚本:
php -d extension=mbstring.so -d extension=openssl.so -r "require 'vendor/autoload.php'; echo 'OK';"—— 显式加载扩展,绕过 php.ini 配置漂移


















