composer的scripts不是自动执行的钩子系统,仅在明确生命周期条件满足时触发;post-install-cmd仅在真正从零安装(vendor不存在或lock不匹配)时运行,而post-update-cmd更可靠,每次update后稳定触发且autoload已就绪。

Composer 的 scripts 不是“写完就自动跑”的钩子系统,它只在明确满足生命周期条件时才触发;多数脚本静默不执行,根本原因不是配置错,而是执行时机没对上。
post-install-cmd 为什么经常不运行
它只在真正从零安装依赖时触发:vendor 目录不存在或为空、composer.lock 缺失或与 composer.json 不匹配,且未加 --no-scripts。本地反复运行 composer install 没反应,大概率是因为 vendor 已存在,Composer 直接跳过初始化流程。
- 检查是否误用了
post-root-package-install或post-create-project-cmd—— 这两个只在create-project场景下触发,普通 install/update 完全不走 - CI 环境默认可能带
--no-scripts,需显式去掉才能让脚本生效 - 脚本名必须严格为
"post-install-cmd",大小写、下划线、驼峰写法(如PostInstallCmd)都会静默失效 - 加一句
echo "post-install-cmd triggered"到脚本开头,是最快确认是否进来的办法
post-update-cmd 是更可靠的部署入口
它在每次 composer update 成功后稳定触发,包括首次 install 后的第一次 update,且能确保 vendor/autoload.php 已就绪,适合做初始化逻辑(如生成配置、清缓存、检查迁移状态)。
- 不要把关键初始化逻辑只塞进
post-install-cmd,否则首次 install 后直接update就会漏掉 - PHP 脚本里必须显式
require __DIR__ . '/../vendor/autoload.php',不能依赖 Composer 自动加载——钩子执行时类加载器可能还没完全激活 - 用
php scripts/post-update.php比写成["MyClass::run"]更安全,避免因命名空间未注册或类文件未声明 autoload 导致Class not found - Linux/macOS 下记得
chmod +x scripts/post-update.php;Windows 可忽略,但别加#!/usr/bin/env php,Composer 不走 shebang
脚本里调用 artisan 或其他命令的坑
看似简单的 php artisan config:clear,实际常因路径、权限、PHP 环境不一致而失败。
- 一律用
@php开头(如"@php artisan config:clear"),确保调用的是 Composer 绑定的 PHP,而非系统 PATH 中的任意版本 - 不要写
./artisan或artisan—— 它可能没有可执行位,应统一用php artisan - 避免
cd ../some-dir,Composer 执行时工作目录就是composer.json所在路径,硬切反而导致路径错乱 - 敏感操作如
chmod -R 755 storage/要注意部署用户和 Web 服务器用户不一致,建议改用chown -R www-data:www-data storage/或交由部署脚本统一处理
调试脚本不执行的最简路径
别先查文档,先看三件事:
- 运行
composer install --verbose,观察输出里有没有Running script post-install-cmd这行 —— 没有就说明根本没触发 - 确认当前目录下
vendor/是否存在,composer.lock是否比composer.json旧(改了 require 却没更新 lock) - 把脚本第一行换成
echo "running $(date)"; exit;,再跑一次,看终端是否打出时间戳 —— 没打就是配置没生效,打了但后续没效果,就是脚本内部逻辑问题
真正难的不是写脚本,而是理解 Composer 的执行上下文:它不保证环境干净、不保证扩展已启用、不保证你写的路径一定可达。每一步都要当作“可能失败”来防御性写。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











