heroku默认php buildpack不执行compile脚本,需用heroku-buildpack-multi配合自定义buildpack;推荐优先使用composer.json的scripts(如post-install-cmd)实现自定义逻辑,所有路径、命令和环境变量须显式指定。

Heroku上composer不执行自定义compile脚本?因为buildpack没生效
Heroku默认的PHP buildpack会自动运行composer install,但不会执行你项目根目录下的compile脚本——除非你显式指定并配置了支持该脚本的buildpack。它只在你用heroku-buildpack-multi或自定义buildpack时才可能被调用。
常见错误现象:compile文件存在、有执行权限、内容也正确,但部署日志里完全看不到它的输出;或者报错command not found: compile。
- 确认是否真的在用支持
compile的buildpack:运行heroku buildpacks,输出应包含类似https://github.com/heroku/heroku-buildpack-php(官方PHP buildpack本身不支持compile)或你自己的fork - 若想用
compile,必须用heroku-buildpack-multi+ 自定义buildpack组合,且把自定义buildpack放在PHP buildpack之前 -
compile脚本必须放在.buildpacks同级目录,且是可执行文件:chmod +x compile - 脚本开头必须带shebang,比如
#!/usr/bin/env bash,否则Heroku执行失败
如何让Heroku在composer install前/后运行自定义逻辑?
官方PHP buildpack不提供钩子,但可以通过覆盖composer.json中的scripts字段间接实现,这是最稳定、无需改buildpack的方式。
使用场景:需要在composer install后生成配置文件、复制env变量到.env、预编译前端资源等。
- 在
composer.json的scripts里加post-install-cmd或pre-install-cmd,例如:"post-install-cmd": ["cp .env.production .env", "php artisan config:clear"] - 确保
composer install --no-dev --optimize-autoloader在Heroku上实际执行的是这个完整流程(默认就是) - 注意:Heroku的PHP buildpack会自动识别并运行这些scripts,无需额外配置
- 避免在
post-install-cmd里做耗时操作(如npm install),容易超时;Heroku slug编译有20分钟限制
自定义buildpack中compile脚本读不到COMPOSER_HOME或PATH?
Heroku buildpack运行环境非常精简,compile脚本启动时没有加载用户shell配置,PATH只有/app/.heroku/php/bin:/usr/local/bin:/usr/bin:/bin,COMPOSER_HOME也未设置。
容易踩的坑:脚本里直接写composer dump-autoload -o,结果报command not found;或用~/.composer路径访问缓存,但实际目录不存在。
- 显式指定composer路径:
/app/.heroku/php/bin/composer(这是Heroku PHP buildpack安装composer的位置) - 设置
COMPOSER_HOME指向可写位置:export COMPOSER_HOME="/tmp/composer"(/tmp在build阶段可用) - 不要依赖
$HOME,Heroku build阶段$HOME是/tmp/build_*临时路径,每次不同 - 所有路径用绝对路径,避免
cd ..类操作——当前工作目录不固定,可能是/tmp/build_abc或/app
为什么composer install在本地成功,但在Heroku上报class not found?
不是autoload问题,而是Heroku默认启用--no-dev且跳过autoload-dev,同时vendor/autoload.php生成方式与本地不同。
性能与兼容性影响:Heroku PHP buildpack会强制运行composer install --no-dev --optimize-autoloader --no-interaction,忽略composer.json里的config.platform,除非你手动干预。
- 检查
autoload-dev里注册的类是否被误用于生产环境(比如测试工具类被业务代码引用) - 如果必须保留dev依赖,设
COMPOSER_FLAGS="--no-optimize-autoloader"(通过heroku config:set),但会拖慢启动速度 - 更稳妥的做法:把真正需要的类移到
autoload而非autoload-dev,或用files方式require单个PHP文件 - 验证方式:部署后进入
heroku run bash,手动执行/app/.heroku/php/bin/composer dump-autoload -o,再php -r "include 'vendor/autoload.php'; echo class_exists('YourClass') ? 'ok' : 'fail';"
compile,优先用composer.json的scripts;所有路径、命令、环境变量都得硬编码或显式导出;vendor行为差异比想象中更隐蔽。










