如何配置并详解Composer的post-install钩子脚本执行过程?

2026-05-17 12:092阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计931个文字,预计阅读时间需要4分钟。

如何配置并详解Composer的post-install钩子脚本执行过程?

`post-install-cmd 不是每次执行的命令,它仅在软件安装后执行一次。

post-install-cmd 触发条件很具体

很多人配好了脚本却没反应,根本原因不是写错了命令,而是压根没满足触发前提:

  • 项目已有 vendor/composer.lock 没变 → Composer 跳过安装流程,post-install-cmd 不执行
  • composer install --no-scripts(CI 环境常默认启用)→ 所有脚本被静默禁用
  • composer.lock 存在但内容过期(比如改了 composer.json 的 require 却没更新 lock)→ 此时 Composer 会先重生成 lock,再安装,post-install-cmd 才会跑
  • 事件名写成 PostInstallpost_install_cmdpost-install → Composer 完全不识别,必须严格为 post-install-cmd(全小写、短横线)

在 composer.json 中正确声明脚本

必须放在顶层 scripts 字段下,值必须是数组(5.6+ 强制要求),不能是单字符串:

{ "scripts": { "post-install-cmd": [ "@php -r \"file_put_contents('runtime/.installed', date('c'));\"", "php artisan config:clear", "php bin/generate-config.php" ] } }

关键点:

  • @php 开头的命令会被 Composer 替换为当前 PHP 可执行路径,比硬写 php 更可靠
  • 外部命令如 npm install 要求系统 PATH 中存在 npm,CI 镜像里得提前装 Node.js
  • PHP 脚本建议用 php -f script.php,不用 ./script.php(可能无执行权限)
  • 不要在脚本里用 __DIR__ 推导路径——Composer 是用 proc_open 启新进程,__DIR__ 指向的是 PHP 解释器位置,不是你的脚本目录

常见失败原因:权限、路径、时机

脚本报错或静默跳过,往往卡在这几个实际问题上:

  • sh: 1: npm: not found → CI 容器没装 Node.js,不能只看本地有就认为线上也有
  • Permission denied: ./artisan → Laravel 的 artisan 缺少可执行位,应改用 php artisan
  • 相对路径失效(如 ../config/app.php)→ 当前工作目录是 composer.json 所在目录,不是脚本所在目录;推荐用 __DIR__ . '/vendor/autoload.php' 显式引入自动加载
  • 脚本里用了未启用的 PHP 扩展(如 mbstring),而容器里没装 → 运行直接崩,但 Composer 默认不报详细错误
  • 想读 composer.json 内容?别 file_get_contents(__DIR__ . '/../composer.json') —— 改用 ComposerInstalledVersions::getRawData()(v2+)更稳定

和 post-update-cmd、post-autoload-dump 的区别

这三个钩子时机不同,混用容易出问题:

  • post-install-cmd:只在 composer install 真正安装依赖后触发(适合部署初始化)
  • post-update-cmd:在 composer updatecomposer install --update 时都稳定触发(更适合开发阶段同步变更)
  • post-autoload-dump:每次自动生成 autoload 文件后都触发(包括 install/update),时机稍晚但更频繁(适合缓存清理、代理类生成)

真正难搞的不是怎么写,而是判断该用哪个钩子——尤其在 CI 流水线里,composer install 行为会因 vendor/ 和 lock 文件状态动态变化,不验证就假设“肯定执行”会踩坑。

标签:Composer

本文共计931个文字,预计阅读时间需要4分钟。

如何配置并详解Composer的post-install钩子脚本执行过程?

`post-install-cmd 不是每次执行的命令,它仅在软件安装后执行一次。

post-install-cmd 触发条件很具体

很多人配好了脚本却没反应,根本原因不是写错了命令,而是压根没满足触发前提:

  • 项目已有 vendor/composer.lock 没变 → Composer 跳过安装流程,post-install-cmd 不执行
  • composer install --no-scripts(CI 环境常默认启用)→ 所有脚本被静默禁用
  • composer.lock 存在但内容过期(比如改了 composer.json 的 require 却没更新 lock)→ 此时 Composer 会先重生成 lock,再安装,post-install-cmd 才会跑
  • 事件名写成 PostInstallpost_install_cmdpost-install → Composer 完全不识别,必须严格为 post-install-cmd(全小写、短横线)

在 composer.json 中正确声明脚本

必须放在顶层 scripts 字段下,值必须是数组(5.6+ 强制要求),不能是单字符串:

{ "scripts": { "post-install-cmd": [ "@php -r \"file_put_contents('runtime/.installed', date('c'));\"", "php artisan config:clear", "php bin/generate-config.php" ] } }

关键点:

  • @php 开头的命令会被 Composer 替换为当前 PHP 可执行路径,比硬写 php 更可靠
  • 外部命令如 npm install 要求系统 PATH 中存在 npm,CI 镜像里得提前装 Node.js
  • PHP 脚本建议用 php -f script.php,不用 ./script.php(可能无执行权限)
  • 不要在脚本里用 __DIR__ 推导路径——Composer 是用 proc_open 启新进程,__DIR__ 指向的是 PHP 解释器位置,不是你的脚本目录

常见失败原因:权限、路径、时机

脚本报错或静默跳过,往往卡在这几个实际问题上:

  • sh: 1: npm: not found → CI 容器没装 Node.js,不能只看本地有就认为线上也有
  • Permission denied: ./artisan → Laravel 的 artisan 缺少可执行位,应改用 php artisan
  • 相对路径失效(如 ../config/app.php)→ 当前工作目录是 composer.json 所在目录,不是脚本所在目录;推荐用 __DIR__ . '/vendor/autoload.php' 显式引入自动加载
  • 脚本里用了未启用的 PHP 扩展(如 mbstring),而容器里没装 → 运行直接崩,但 Composer 默认不报详细错误
  • 想读 composer.json 内容?别 file_get_contents(__DIR__ . '/../composer.json') —— 改用 ComposerInstalledVersions::getRawData()(v2+)更稳定

和 post-update-cmd、post-autoload-dump 的区别

这三个钩子时机不同,混用容易出问题:

  • post-install-cmd:只在 composer install 真正安装依赖后触发(适合部署初始化)
  • post-update-cmd:在 composer updatecomposer install --update 时都稳定触发(更适合开发阶段同步变更)
  • post-autoload-dump:每次自动生成 autoload 文件后都触发(包括 install/update),时机稍晚但更频繁(适合缓存清理、代理类生成)

真正难搞的不是怎么写,而是判断该用哪个钩子——尤其在 CI 流水线里,composer install 行为会因 vendor/ 和 lock 文件状态动态变化,不验证就假设“肯定执行”会踩坑。

标签:Composer