scripts-dev 不是 Composer 标准字段,会被忽略;所有脚本必须定义在顶层 scripts 下,通过环境变量(如 COMPOSER_DEV_MODE)或条件判断区分开发/生产逻辑。

composer.json 里 scripts-dev 不是标准字段
Composer 官方根本不认识 scripts-dev 这个键。你如果直接写进去,composer install 或 composer run 都会忽略它——不会报错,但也不会执行。所有自定义脚本必须定义在顶层的 scripts 字段下。
用环境变量 + script 钩子区分开发/生产脚本
真正可行的做法是:把开发专用命令放进 scripts,再通过条件判断或环境变量控制是否执行。常见组合有:
- 用
if命令(Shell)判断COMPOSER_DEV_MODE或自定义变量,比如:\"post-install-cmd\": \"if [ \\\"$COMPOSER_DEV_MODE\\\" = \\\"1\\\" ]; then php bin/console cache:clear; fi\"
- 配合
composer run的--no-dev行为:把开发脚本设为只在--dev模式下触发(默认就是),再在脚本里加 guard,例如:\"dev-check\": \"php -r 'if (!getenv(\\\"COMPOSER_DEV_MODE\\\")) { exit(1); } echo \\\"dev mode confirmed\\n\\\";' - 拆成两个 script 条目,命名带标识,靠人肉调用:
\"dev:setup\": \"php bin/console doctrine:schema:create && php bin/console hautelook:fixtures:load --no-interaction\",\n\"prod:deploy\": \"php bin/console cache:warmup --env=prod\"
避免在 post-autoload-dump 中无条件执行开发命令
很多人把 phpstan analyse 或 phpcs 塞进 post-autoload-dump,结果上线部署时也跑,拖慢构建、暴露敏感路径、甚至因缺少 dev 依赖而失败。正确做法是:
- 只在明确的开发命令中调用静态分析工具,例如:
\"dev:analyze\": \"phpstan analyse src/ --level max\"
- 若必须钩子化,加判断:
\"post-autoload-dump\": [\"@dev:check\", \"if [ \\\"$CI\\\" != \\\"true\\\" ] && [ \\\"$COMPOSER_DEV_MODE\\\" = \\\"1\\\" ]; then phpstan analyse src/ --no-progress; fi\"]
- 注意
COMPOSER_DEV_MODE在composer install --no-dev时为0,但该变量不一定被所有环境自动注入,建议显式传入:COMPOSER_DEV_MODE=1 composer run dev:setup
script 名称里带冒号不等于作用域隔离
dev:watch、test:unit 这类命名只是便于阅读和分组,Composer 不会因此限制执行环境或自动跳过。它们和 watch、unit 在机制上完全等价。真正起作用的是你脚本内容里的判断逻辑,不是名字里的冒号。
最容易被忽略的一点:脚本是否执行,取决于你调用时的上下文(composer run xxx)、环境变量、以及脚本内部是否做了防御性检查——而不是字段名、命名风格或是否写了 -dev 后缀。










