composer scripts需手动触发,不自动执行;php脚本须显式引入autoload.php;传参用--分隔;钩子失败行为依pre/post类型而异。

直接在 composer.json 的 scripts 里定义命令,比 shell 别名或全局工具更可靠——它随项目走、自动加载 vendor/autoload.php、支持参数和环境变量,且无需额外安装。
怎么写一个可传参的 dev:serve 脚本
你不想每次输 php -S localhost:8000 -t public,但又希望端口和目录能灵活改。
- 在
scripts中用字符串加-- {@}声明参数接收点:"dev:serve": "php -S $HOST:$PORT -t $PUBLIC_DIR -- {@}" - 调用时传参:
composer run dev:serve -- --bind 127.0.0.1:8080(--后的内容会透传给 PHP 内置服务器) - 环境变量需提前设置:
HOST=127.0.0.1 PORT=8080 PUBLIC_DIR=public composer run dev:serve - 注意 JSON 字符串内双引号要转义,否则
composer install会报JSON decode error
为什么数组形式脚本比单字符串更安全
当你需要顺序执行多条命令(比如迁移 + 清缓存),用数组能明确失败边界,避免“半截执行”。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 错误写法(单字符串拼接):
"dev:setup": "php artisan migrate --seed && php artisan optimize:clear"—— 第一条失败,第二条仍可能被 shell 尝试执行 - 正确写法(数组):
"dev:setup": ["php artisan migrate --seed", "php artisan optimize:clear"]—— 第一条失败,Composer 直接中止,不执行后续 - 数组还天然兼容 Windows:不用处理
&&在 cmd.exe 下的解析差异 - 若某条命令需忽略失败继续,可显式加
|| true,但应加注释说明理由
如何让脚本在 CI 和本地行为一致
CI 环境常禁用脚本(--no-scripts),但你写的自定义命令如 test:unit 仍需可用 —— 关键是别把它们混进生命周期钩子。
- 把可选操作(如构建前端、跑测试)全放在自定义脚本名下(如
test:unit,build:frontend),**不要塞进post-install-cmd** - 生命周期钩子只放真正不可跳过的初始化逻辑(如
key:generate),否则 CI 加了--no-scripts就直接崩 - 用
$COMPOSER_BIN_DIR替代硬编码路径:"$COMPOSER_BIN_DIR/phpunit",避免不同项目vendor/bin被重命名导致失败 - CI 中推荐分两步:
composer install --no-scripts→composer run test:unit,控制权始终在你手上
哪些坑最容易导致脚本静默失败
脚本看起来跑完了,但实际没生效,这类问题最难排查。
- Windows 下路径分隔符写死:
"php ./tests/run.php"在 Windows 可能失败,改用"php tests/run.php"(去掉./) - PHP 版本不一致:脚本里用了
match表达式,但 CI 用的是 PHP 8.0 —— 没报错,只是跳过整段逻辑 - 依赖未 autoload:脚本里调用
App\EnvChecker,但composer dump-autoload没触发,类找不到也不报错(除非加-d display_errors=1) - 权限问题:脚本生成文件到
bootstrap/cache/,但 Docker 容器里该目录非可写,命令返回 0 却什么都没写成
最麻烦的不是脚本写不出来,而是它在某个环境里“看似运行了”,实则什么都没干 —— 动手前先确认它依赖的路径、类、二进制是否存在,比加 --verbose 更有效。










