scripts脚本需定义在composer.json的scripts字段下,键为自定义命令名,值为命令字符串或数组;必须通过composer run-script显式调用或绑定到Composer内置生命周期事件(如post-install-cmd)才生效。

composer.json 里 scripts 怎么写才生效
脚本必须定义在 scripts 字段下,且键名是自定义命令名,值是具体要执行的命令或数组。Composer 不会自动运行任何脚本,必须显式调用 composer run-script xxx 或绑定到生命周期事件(如 post-install-cmd)才能触发。
- 直接写字符串:支持单条 shell 命令,比如
"php -v";跨平台建议用 PHP 脚本代替 shell 片段 - 写数组:按顺序执行多条命令,但 Windows 和 Linux 对分号/&& 处理不一致,容易失败,慎用
- 脚本名不能含空格或特殊字符,否则
composer run-script会报错Script xxx not found - 如果脚本里调用了项目中未安装的二进制(比如
phpcs),得确保它在vendor/bin/下,或用php vendor/bin/phpcs显式路径
哪些钩子名是 Composer 真正识别的生命周期事件
不是随便起个名字就能当钩子——只有 Composer 内置的事件名才会被自动触发。比如 post-autoload-dump 是标准事件,而 after-install 就不会被响应。
- 常用有效钩子:
pre-install-cmd、post-install-cmd、pre-update-cmd、post-update-cmd、post-autoload-dump - 注意拼写:少个
-cmd后缀(如写成post-install)就完全无效,也不会报错,静默忽略 - 多个脚本绑定同一事件时,按
composer.json中定义顺序执行,但无法控制依赖关系 - 钩子函数本身不传参,想区分 install 还是 update?得靠检测
composer.lock是否存在或比对 vendor 目录时间戳
PHP 脚本作为 script 执行时的路径和加载问题
用 "php scripts/check.php" 这种方式调用 PHP 文件时,当前工作目录是项目根目录,但 __DIR__ 在脚本内指向的是 scripts/ 目录,不是项目根目录。很多路径错误都源于此。
- 不要硬写
require 'vendor/autoload.php'—— 应该用require __DIR__.'/../vendor/autoload.php';或更稳妥地用require_once getcwd().'/vendor/autoload.php'; - 如果脚本依赖 Laravel 或 Symfony 的服务容器,别指望自动加载完成后再执行——
post-autoload-dump是唯一能确保 autoloader 已生成的时机 - 调试时加
echo getcwd();和var_dump(__DIR__);,比猜快得多 - Windows 下反斜杠路径可能引发 require 失败,统一用
dirname(__DIR__)拼接
为什么 post-update-cmd 有时不执行,或只执行一半
常见原因是脚本中途 exit 或抛出未捕获异常,导致后续脚本中断;另一个隐蔽问题是 Composer 并行执行某些内部操作,而你的脚本假设了顺序。
-
composer update默认跳过已满足的包,如果某脚本依赖某个包更新才触发逻辑,它可能根本不会跑——改用post-autoload-dump更可靠 - 脚本里用
die()或exit(1)会让整个 Composer 命令退出,后续钩子全丢弃;改用throw new RuntimeException()并捕获处理 - 避免在钩子里做耗时操作(如下载、编译),用户执行
composer install时卡住,会直接删掉scripts段落 - CI 环境中
COMPOSER_NO_INTERACTION=1可能影响某些交互式脚本行为,提前用getenv('CI')分支判断










