composer install 时需加 --interactive 参数才能手动输入 yes/no,但仅对删除 vendor、信任包来源等部分操作生效,不会逐个依赖提示;create-project 和 update 同理,需确保终端交互可用且未被环境变量或管道阻断。

composer install 时怎么手动输入 yes/no
默认情况下 composer install 走静默模式,不问你任何问题;想让它停下来等你确认(比如要不要删除 vendor、是否信任包来源),得加 --interactive 参数。
但注意:这个参数只对部分操作生效,比如删除旧 vendor 目录、安装前确认可信性提示(尤其是启用了 secure-http 或遇到非 HTTPS 包源时)。它不会让每个依赖都弹出确认——Composer 不是包管理器的“向导模式”,没那么细粒度。
-
composer install --interactive是最常用写法,适合 CI 以外的本地开发环境 - 如果已经跑过一次 install,再执行时通常不会重复提问,除非
composer.lock变了或 vendor 被删了 - 某些插件(如
hirak/prestissimo)可能屏蔽交互提示,建议临时禁用测试
为什么 composer create-project 不让你选选项
composer create-project 默认跳过所有交互,哪怕模板里写了 scripts 或 post-create-project-cmd 钩子要读 stdin,也大概率收不到输入——因为 Composer 在该命令下会主动关闭 stdin 流。
解决办法只有一个:显式加 --interactive,而且必须放在命令末尾(参数顺序敏感):
composer create-project laravel/laravel myapp --interactive
常见失效场景:
- 在 Docker 容器里运行,没加
-t(分配伪 TTY),--interactive形同虚设 - 用
bash -c "composer create-project ..."包了一层,stdin 被截断 - 项目模板的
composer.json里写了"config": {"interactive": false},会强制覆盖命令行参数
composer update 出现 “Do you want to continue?” 却不暂停
这个提示一般来自两个地方:一是 Composer 自身检测到重大变更(如 PHP 版本不兼容),二是第三方插件(比如 roave/security-advisories 的钩子)主动调用 IOInterface::askConfirmation()。但它不暂停,往往是因为:
- 当前终端不是交互式终端(
php_sapi_name() === 'cli'但posix_isatty(STDIN)返回 false) - 设置了环境变量
COMPOSER_NO_INTERACTION=1(CI 环境常见,默认启用) - 你在管道里运行,比如
composer update | grep ...,stdin 被重定向
验证方式很简单:
php -r "var_dump(posix_isatty(STDIN));"
返回 false 就说明终端不被识别为交互式,加 --interactive 也没用——得从运行环境入手,比如加 -t(Docker)、script -qec(macOS/Linux)、或改用 expect 脚本模拟输入。
如何让某个脚本步骤一定可交互
如果你在 composer.json 的 scripts 里写了自定义命令,又希望它能读用户输入(比如问“要清空数据库吗?”),不能只靠 --interactive ——Composer 不会自动把 stdin 透传给子进程。
正确做法是:在脚本中显式检查交互能力,并用 PHP 原生方式读取:
#!/usr/bin/env php
<?php
if (!posix_isatty(STDIN)) {
throw new RuntimeException('Not running in interactive terminal');
}
echo "Drop database? (yes/no): ";
$input = trim(fgets(STDIN));
if ($input !== 'yes') exit(1);
// ... proceed
然后在 composer.json 中这样注册:
"scripts": {
"drop-db": [
"@php scripts/drop-db.php"
]
}
关键点:
- 别用
shell_exec()或system()执行带交互的命令,它们拿不到 stdin - PHP 脚本里必须自己调
fgets(STDIN),不能指望 Composer 替你转发 - CI 环境下这类脚本应加 guard 判断,否则直接卡住
交互这件事,在 Composer 里从来不是“打开开关就全通”,而是每一步都要确认终端可用、stdin 未被劫持、脚本自己有读取逻辑——漏掉任意一环,就会安静地失败或卡死。










