不能直接在生产服务器运行 composer install,因生产环境常禁用 shell、缺 php cli 或扩展(如 openssl/zlib),导致 command “install” 未定义或网络解析失败;必须本地构建并严格使用 –no-dev –optimize-autoloader –no-interaction 三参数,rsync 同步时需排除 .git 和各类 tests 目录,但保留 autoload_*.php,并验证 vendor/autoload.php 可被成功 require。

为什么不能直接在生产服务器运行 composer install
因为生产服务器常禁用 shell 访问、无 PHP CLI 环境、缺扩展(如 openssl、zlib),或被安全策略限制执行外部命令。硬上会报错,比如:Command "install" is not defined 或 file_get_contents(): php_network_getaddresses: getaddrinfo failed——根本连不上 Packagist。
本地构建必须用 --no-dev --optimize-autoloader --no-interaction
这三参数不是可选项,是防止线上出问题的底线:
-
--no-dev:跳过require-dev里的包(如 PHPUnit、phpstan),避免把开发工具打进生产环境 -
--optimize-autoloader:生成扁平化autoload_classmap.php,减少class_exists()查找开销,启动快 20%+(尤其 laravel/symfony 项目) -
--no-interaction:禁掉所有交互提示(比如是否启用插件),否则 CI/脚本会卡住
正确命令:composer install --no-dev --optimize-autoloader --no-interaction。漏掉任一参数,都可能让同步后的代码跑不起来或性能异常。
rsync 同步时要排除哪些目录和文件?
直接 rsync -av ./vendor/ user@prod:/var/www/app/vendor/ 是危险的——会把本地调试痕迹、临时文件甚至 .git 目录一起推上去。
- 必须排除:
vendor/.git(体积大,且无意义)、vendor/*/Tests(测试代码无需上线) - 建议排除:
vendor/*/tests、vendor/*/test、vendor/*/phpunit.xml*(大小写不敏感场景下漏掉小写 test 会导致误传) - 别忽略:
vendor/composer/autoload_*.php—— 这些是composer dump-autoload生成的,必须随 vendor 一起同步,否则Class not found
推荐 rsync 命令片段:rsync -av --exclude='.git' --exclude='*/Tests' --exclude='*/tests' ./vendor/ user@prod:/var/www/app/
部署后还要检查 vendor/autoload.php 是否可 require
常见坑:本地 PHP 版本是 8.2,生产是 7.4,但 composer install 没加 --ignore-platform-reqs,导致某些包降级失败,autoload.php 里引用了不存在的类。
- 上线后第一件事:在生产机上跑
php -r "require 'vendor/autoload.php'; echo 'OK';" - 如果报
ParseError或Class not found,说明本地构建环境和生产 PHP 版本/扩展不一致 - 补救方法:本地用和生产一致的 PHP 版本重装依赖(如
docker run --rm -v $(pwd):/app -w /app php:7.4-cli composer install ...)
autoload.php 不是“存在就行”,它得能被 PHP 成功解析并注册自动加载器——这是整个依赖链最脆弱的一环。