在composer.json的scripts字段中需写字符串命令(如"php scripts/test.php")或数组,路径相对项目根目录;PHP脚本须手动require DIR . '/vendor/autoload.php'并用__DIR__处理路径,参数需脚本内解析,@php确保使用Composer指定PHP版本。

直接在 composer.json 的 scripts 字段里写命令行调用,就能让 composer run 执行你的 PHP 脚本——但脚本本身必须手动加载 vendor/autoload.php,路径要用 __DIR__,参数得自己解析,@php 前缀才能确保用 Composer 指定的 PHP 版本运行。
怎么在 composer.json 里正确配置 scripts 字段
scripts 不是写 PHP 逻辑的地方,它只接收字符串命令或命令数组。值必须是 shell 可执行的语句,比如 "php scripts/deploy.php" 或 "@php scripts/clean.php --env=prod"。
- 脚本名(如
dev:setup)完全自定义,运行时用composer run dev:setup - 路径始终相对于项目根目录,别写
./src/xxx.php却把文件放在bin/下 - 想复用其他 script,用
@script-name引用,比如"@clear-cache" - 如果命令含空格或特殊字符,整个字符串用双引号包裹,避免 shell 解析错误
PHP 脚本里为什么必须手动 require autoload.php
Composer 不会自动为你引入自动加载器,它只负责调起进程执行命令。不加这句,你连自己的类、框架类、第三方包都用不了。
- 固定写法是
require __DIR__ . '/vendor/autoload.php';,__DIR__确保路径不随调用位置偏移 - 不要用
dirname(__FILE__)或getcwd(),它们在某些 CLI 场景下不可靠 - 如果你的脚本放在
scripts/目录,而项目根目录有vendor/,那就必须从__DIR__往上退一级:例如require __DIR__ . '/../vendor/autoload.php';
如何安全传参并避免 shell 注入
Composer 不解析脚本参数,全靠你在 PHP 里处理。直接拼接 $argv 或用 getopt() 是最常见方式,但要注意过滤。
- 别用
exec("php some.php $argv[1]")这类拼接,用户传入foo; rm -rf /就炸了 - 推荐用
getopt()做白名单解析,比如只允许-e|--env和-v|--verbose - 如果必须支持自由参数,用
escapeshellarg()包裹每个参数再传给子进程 -
@php前缀能绕过系统默认 PHP,强制使用 Composer 配置的版本,对多 PHP 版本环境很关键
常见报错和对应检查点
跑不起来?八成卡在这几个地方:
-
Could not open input file: scripts/foo.php→ 检查路径是否真在项目根目录下,不是相对composer.json所在位置 -
Class 'App\Console' not found→ 忘了require vendor/autoload.php,或路径写错了 -
command not found: php→ 系统没配 PHP 环境变量,改用@php前缀 - 脚本输出乱码或无响应 → 检查脚本开头有没有
#!/usr/bin/env php,以及是否加了chmod +x(仅当直接执行脚本文件时需要)
真正容易被忽略的是:所有脚本命令都走 shell 层,哪怕你写的是 PHP 文件,也得当成 shell 命令去调试——先在终端里手动敲一遍 php scripts/do.php --dry-run,确认能跑通,再塞进 composer.json。否则你会花半小时找 JSON 格式错误,其实问题出在脚本第一行少了个分号。











