配置文件同步不应放在 post-install-cmd 中,而应作为独立部署步骤;需用绝对路径、显式权限处理、来源校验及 PHP 封装逻辑确保可靠性和跨环境一致性。

脚本执行时当前目录不一定是项目根目录
很多人写 cp config/local.php ./config/ 发现报错“no such file or directory”,其实是因为 Composer 运行脚本时 CWD 是 composer.json 所在路径,但相对路径解析仍以该目录为基准——而你期望的 ./config/ 可能并不存在于当前上下文。更稳妥的做法是用 ${PWD} 或 $(pwd) 锚定绝对路径。
同步配置文件必须显式处理权限和覆盖逻辑
直接 cp 会失败常见于两类场景:目标目录不可写(如部署用户是 www-data,但脚本以 root 运行),或源文件不存在导致静默跳过。建议在脚本中加入判断:
- 用
test -f "${PWD}/config/local.php.example" && cp ...避免源缺失时报错中断 - 用
chown -R www-data:www-data "${PWD}/config/local.php"确保 Web 进程可读(若需) - 加
set -e开头让任意命令失败立即退出,别让后续步骤在错误状态下继续
post-install-cmd 不适合首次部署时的配置初始化
post-install-cmd 只在 composer install 成功后触发,但此时 config/local.php 往往还没放到位——它通常由部署流程单独拷贝,早于 composer install。硬塞进 post-install-cmd 容易因文件未就绪而失败。
更可靠的方式是:把同步逻辑拆成独立脚本,比如 "scripts": { "deploy:sync-config": "bash scripts/sync-config.sh" },然后在部署命令里显式调用:cp config/local.php.example config/local.php && composer run deploy:sync-config。
环境变量和条件判断不能靠 shell 内置逻辑硬编码
别在脚本里写 if [ "$APP_ENV" = "prod" ]; then cp config/prod.php config/local.php; fi——$APP_ENV 在 Composer 脚本执行时不一定被导出,且不同系统对 [ 的兼容性不一。
推荐方案:
- 用 PHP 封装逻辑:
"deploy:sync-config": "php -r \"copy(\$_ENV['CONFIG_SRC'] ?? 'config/local.php.example', \$_ENV['CONFIG_DST'] ?? 'config/local.php');\"" - 或统一通过
COMPOSER_ARGS传参:composer run deploy:sync-config -- --env=prod,再由 PHP 脚本解析 - 避免在
scripts字段里写多行 shell 命令,跨平台兼容性差,调试困难
实际最常被忽略的一点:配置文件同步不是 Composer 的职责,而是部署流程的边界动作。把它塞进 post-install-cmd 看似省事,实则模糊了构建、部署、运行三阶段的界限,导致本地开发、CI 流水线、生产部署行为不一致。











