生产环境必须用 composer install --no-dev --optimize-autoloader,漏一不可:--no-dev 防止 phpunit 等开发包上线引入安全与加载冲突风险,--optimize-autoloader 生成 classmap 规避反复 stat() 导致的 I/O 性能拖累;二者需同时使用,缺一即失效。

生产环境必须用 composer install --no-dev --optimize-autoloader
不加这两个参数就上线,等于主动引入安全风险和性能拖累。漏掉 --no-dev 会让 phpunit、symfony/debug-bundle 这类开发包被装进 vendor/,不仅增大部署体积,还可能因自动加载规则冲突导致 Class 'Tests\TestCase' not found;漏掉 --optimize-autoloader(或简写 -o)则 autoload 仍靠遍历文件路径,每次 new 一个类都要反复 stat(),I/O 开销肉眼可见。
二者必须同时出现——只去 dev 包但不优化,classmap 还是空的;只优化但留着 dev 包,反而让 classmap 更大、更慢。
-
--no-dev:跳过require-dev声明的所有包,且移除autoload-dev规则(比如 PSR-4 映射到tests/的部分) -
--optimize-autoloader:生成vendor/composer/autoload_classmap.php,把类名直接映射到文件路径,绕过所有动态查找 - 额外推荐加
--no-interaction -n防卡在插件提示,加--prefer-dist强制走 zip 包而非 git clone,更快更稳
不能在生产机上运行 composer install
PHP-FPM 进程权限、umask、SELinux 策略、opcache 缓存时间戳校验,任何一个都可能让 composer install 在线上失败。更现实的问题是:web 用户(如 www-data)通常没权限往 vendor/ 写文件,而用 root 装又留下安全隐患。
正确做法是在 CI/CD 流水线或本地干净环境里执行完整命令,产出已验证的 vendor/ 目录,再整体同步到生产机。
- 构建阶段命令示例:
composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist - 确保
git checkout到目标 tag/branch 后再执行,避免composer.lock和代码版本错位 - 部署包里必须包含
vendor/,但它绝不能进 Git(.gitignore里写好/vendor)
composer.lock 必须由构建环境生成,且上下文一致
同一份 composer.lock 文件,在不同机器上运行 composer install 可能解出不同 vendor/,原因包括:PHP 版本差异、扩展缺失、插件行为变化、甚至网络响应顺序。蓝绿部署时若忽略这点,两个环境实际加载的类可能不一致。
关键不是锁文件“内容一样”,而是“生成它的环境一样”。
- CI/CD 中应固定 PHP 版本(如
php:8.1-cli)、预装必需扩展(ext-pdo、ext-json等) -
composer.json中显式配置"config": {"platform": {"php": "8.1.0"}},禁止 Composer 根据本地环境推测平台能力 - 禁用不兼容插件(如旧版
hirak/prestissimo),必要时加--no-plugins临时绕过
Nginx 和 PHP-FPM 权限与路径安全要手动兜底
Composer 不管 Web 服务器怎么配,但部署后如果 Nginx 允许直接下载 composer.json 或访问 /vendor/,就等于把依赖结构和潜在漏洞路径全暴露出去。
PHP-FPM 的 user/group 也要能读取 vendor/autoload.php 和所有类文件,否则连 502 Bad Gateway 都不报具体原因,只在 php-fpm.log 里沉默失败。
- Nginx 配置中必须加:
location ~ /\.(env|json|lock|git|hg|svn)$ { deny all; } - 显式屏蔽:
location ^~ /vendor/ { return 403; } - 确认
www-data(或对应用户)对vendor/、bootstrap/cache/有r-x权限(目录必须有x才能进入) - opcache 开启且设
validate_timestamps=0,部署后记得opcache_reset()或重启 PHP-FPM
部署真正难的不是命令怎么敲,而是构建环境和生产环境之间那层看不见的“上下文一致性”——PHP 版本、扩展、平台配置、插件状态、甚至时区和 locale,都可能让同一个 composer.lock 在两台机器上产出不同的行为。











