Composer脚本需通过自定义PHP静态方法(如MyScript::checkBeforeBuild)在pre-install-cmd/pre-update-cmd中执行环境或文件检查,使用file_exists()、getenv()等判断,失败时必须exit(1)中断流程,不可依赖return或shell命令跨平台调用。

Composer脚本如何在执行前判断环境或文件是否存在
Composer 脚本本身不支持原生的“条件跳过”,但可以通过包装成 php 命令或调用自定义 PHP 函数,在真正干活前做检查。核心思路是:把前置逻辑写进可执行单元,返回非零退出码就能中断后续脚本链。
- 直接在
scripts里写 shell 命令(Linux/macOS)或批处理(Windows)容易跨平台失效,不推荐 - 更可靠的方式是定义一个 PHP 函数(如
checkBeforeBuild()),在composer.json中通过"pre-build": "MyScript::checkBeforeBuild"调用 - 该函数内部可用
file_exists()、extension_loaded()、getenv()等做判断,检查失败时直接exit(1)或抛出异常 - 注意:Composer 会按顺序执行同名钩子(如所有
pre-install-cmd),任一失败则整个命令终止
为什么用 static function 而不是普通函数
Composer 在调用类方法时只支持 ClassName::methodName 形式,且要求方法为 static。非静态方法会报错:Call to undefined method MyScript::checkBeforeBuild()(实际是因未实例化导致)。
- 类必须可自动加载(放在
autoload.files或符合 PSR-4 规则) - 方法签名建议为
public static function checkBeforeBuild(): int,返回0表示通过,非0表示失败 - 不要依赖
$argv—— Composer 不传参给钩子函数;如需配置,改用环境变量或composer.json的extra字段
pre-install-cmd 和 pre-update-cmd 的检查差异
这两个钩子触发时机不同,前置检查的关注点也不同:
-
pre-install-cmd:适合检查部署环境,比如确认.env文件存在、storage/目录可写、PHP 扩展(如mbstring)已启用 -
pre-update-cmd:更适合校验开发约束,例如运行git status --porcelain确保工作区干净,或检查composer.lock是否被手动修改过 - 两者都**不会**影响
composer install --no-scripts的执行 —— 这个 flag 会跳过全部脚本,包括前置检查
常见错误:检查逻辑没生效或静默跳过
最常踩的坑是误以为“脚本返回 false 就算失败”,其实 Composer 只认进程退出码。PHP 脚本里 return false; 不会中断流程,必须显式 exit(1)。
- 写完检查函数后,务必手动测试:运行
php -r "require 'vendor/autoload.php'; MyScript::checkBeforeBuild();"看是否如预期退出 - 避免在检查中调用可能触发 autoloader 异常的代码(如 new 一个尚未安装的类),否则 Composer 会报错并终止,但错误信息不指向你的检查逻辑
- Windows 下慎用
exec('which')类命令;统一用PHP_BINARY常量或$_SERVER['OS'] ?? ''做轻量适配
Composer 的前置检查本质是“守门人”,它不提供语法糖,但足够灵活。真正复杂的状态判断(比如多步骤依赖校验)建议拆成独立命令,而不是塞进单个钩子函数里。











