因为 composer validate 能在提交前拦截 composer.json 格式错误、字段非法等问题,避免 CI 构建失败;可靠 pre-commit 钩子应仅校验暂存区变动的 composer.json/composer.lock,用 composer validate --no-check-publish --strict 并非零退出中断提交。

为什么 composer validate 要放进 pre-commit?
因为 composer.json 一旦格式错误或字段非法(比如 require 里写了不存在的包名、autoload 路径拼错、JSON 语法不合法),后续 CI 构建或本地 composer install 就会失败。等推到远端再被 CI 拦住,修复成本更高。pre-commit 是最后一道本地防线。
怎么写一个可靠的 pre-commit 钩子?
直接在 .git/hooks/pre-commit 里写 shell 脚本即可,不用额外依赖工具。关键点是:只校验暂存区里真正被修改的 composer.json 和 composer.lock,避免无谓执行;失败时必须退出非零码让 commit 中断。
示例脚本逻辑:
- 用
git diff --cached --name-only --diff-filter=AM | grep -E '^(composer\.json|composer\.lock)$'检查是否有相关文件变动 - 若有,运行
composer validate --no-check-publish --strict:--no-check-publish跳过 Packagist 可达性检查(避免网络问题误伤),--strict启用更严格的 schema 校验(比如警告字段弃用) - 若
composer validate返回非 0 状态码,立即exit 1,并输出提示(如composer.json validation failed)
常见失败场景和对应处理
实际跑起来常遇到几类问题,不是命令写错,而是环境或配置本身有隐性缺陷:
-
composer.json里用了新版本才支持的字段(比如conflict块里用了^2.0但当前 Composer 版本太老),此时升级composer或降级写法更有效,而非关掉--strict - CI 使用的 Composer 版本和本地不一致,导致 pre-commit 过了但 CI 失败 —— 建议在项目根目录加
composer --version输出到.composer-version,钩子里做简单比对 -
composer.lock被修改但没同步更新composer.json(比如手动改了 lock 文件),composer validate默认不报错,需额外加composer install --dry-run来验证 lock 是否与 json 一致
要不要加到 shared hooks 或用 Husky 风格管理?
小团队或单人项目,直接写 .git/hooks/pre-commit 最轻量;多人协作时,composer validate 这种纯 PHP 工具链检查,没必要引入 Node.js 依赖(如 Husky)。但要注意两点:
- 钩子文件本身不会被 git 跟踪,得靠文档或初始化脚本分发(比如
bin/setup-hooks) - Windows 用户可能因换行符或 bash 路径问题失败,建议用
#!/usr/bin/env bash开头,并避免sed -i这类平台敏感操作
真正容易被忽略的是:钩子只拦得住你本地 commit,拦不住 git push --force 或别人绕过钩子提交。所以它只是辅助手段,不能替代 CI 里的 composer validate 步骤。


















