php -d memory_limit=-1 经常失效,因其仅作用于当前PHP进程,而Composer执行链中易因shell wrapper未透传、CLI与FPM配置路径不一致、Windows未加引号、CI禁用-d参数等原因导致未生效。

直接加 php -d memory_limit=-1 最快见效,但多数失败不是因为没加这句,而是它根本没作用到 Composer 进程上。
为什么 php -d memory_limit=-1 经常失效
它只影响当前 PHP 进程,而 Composer 执行链里很容易“漏掉”这个参数:
- 你运行的是
composer install,但系统实际调用的是 shell wrapper 脚本(比如 macOS 的/usr/local/bin/composer),它内部又调用了另一个 PHP 进程——-d参数没透传过去 -
which php和php --ini显示的配置路径不一致:你改了 FPM 的php.ini,但 CLI 模式压根不读它 - Windows PowerShell 下写了
php -d memory_limit=-1 composer install却没加引号:php -d "memory_limit=-1"才对,否则空格后的内容被截断 - CI 环境(如 GitLab Runner)明确禁用
-d参数,此时必须靠COMPOSER_MEMORY_LIMIT=-1配合php -d备用兜底
composer install 和 composer update 的内存消耗差异在哪
名字有误导性:composer update 是标准内存杀手;composer install 理论上轻量,但前提是 composer.lock “干净”:
-
composer update必须重跑 SAT 依赖求解、下载全部元数据、校验所有版本约束——内存峰值常超 1.5GB -
composer install只按composer.lock还原,但如果该文件体积超 5MB(含大量dev-master哈希、废弃包残留),解析反而更耗内存 - 删掉
vendor/和composer.lock后直接composer update,等于强制全量重算+下载+解压,是内存峰值最高的操作组合
真正有效的裁剪组合(尤其 ThinkPHP / CI 场景)
插件和脚本才是内存黑洞,不是 Composer 核心。ThinkPHP 项目本身不依赖全局插件,但 post-install-cmd 或 hirak/prestissimo 这类插件会在安装阶段被加载,显著抬高内存峰值:
-
--no-dev:跳过require-dev中所有包(如phpunit、phpstan),内存常降 40%~60% -
--no-plugins:禁用钩子型插件,避免每个包安装后触发额外逻辑 -
--no-scripts:跳过post-install-cmd等脚本执行,防止执行未知代码放大内存压力 -
--optimize-autoloader(或-o):生成扁平classmap,降低dump-autoload阶段内存峰值
推荐组合:php -d memory_limit=2G composer install --no-dev --no-plugins --no-scripts -o
Docker / CI 环境下容易被忽略的底层限制
COMPOSER_MEMORY_LIMIT=-1 没用——它不能突破 PHP 底层限制,只影响 Composer 自身预分配逻辑:
- 必须前置
php -d memory_limit=1.5G(别用-1,防止单次异常拖垮构建节点) - 确保
composer.lock已提交且未被 CI 缓存污染,否则install会悄悄退化为update - Docker 场景下,还要检查容器内存是否充足(如
docker run --memory=4g),否则即使 PHP 无限制也会被 OOM killer 干掉 - 临时目录(
/tmp或%TEMP%)空间不足也会导致“内存溢出”假象,需同步检查并设置TMPDIR











