php cli脚本通过$argv数组和$argc变量读取命令行参数,$argv[0]为脚本路径,$argv[1]起为用户参数;需检查$argc长度防未定义索引,用getopt()处理--option=value等长选项,windows下中文参数需编码转换,校验应使用array_key_exists()而非isset()。

PHP命令行脚本怎么读取 $argv 和 $argc
PHP CLI 模式下,参数通过全局数组 $argv 传递,$argc 表示总个数(含脚本名)。$argv[0] 是脚本路径,$argv[1] 才是第一个用户传入的参数。
常见错误:直接用 $argv[1] 却没检查长度,导致未定义索引警告;或混淆了 Web 环境下的 $_GET 习惯,试图用 $_SERVER['argv'](不存在)。
-
$argv是普通索引数组,不支持--name=value自动解析,纯靠空格分割 - 带空格的参数必须用引号包裹,如
php script.php "hello world"→$argv[1] === "hello world" - 如果脚本路径含空格(如
/path/to/my script.php),需用引号调用:php "/path/to/my script.php" arg,否则 shell 会截断
如何处理 --option=value 这类长参数
PHP 原生不解析长选项,得自己拆解 $argv 或用 getopt()。后者更可靠,但只支持单字符短选项(-f)和带等号/空格的长选项(--file=xxx 或 --file xxx),不支持 --file xxx --debug 这种无等号且无值的组合写法(除非显式声明为“可选值”)。
示例:
php script.php --host=localhost --port=8080 -v // getopt 配置:'v' => 'verbose', 'host:' => 'host', 'port:' => 'port' // 注意冒号表示该选项必须有值
- 没加冒号的选项(如
'v')会被当作布尔开关,getopt()返回键存在即为 true - 长选项名必须全小写,
--Host或--HOST不会被识别 - 混合使用短/长选项时,
getopt()仍能正确分组,但顺序不能乱:所有选项必须在非选项参数之前,否则后续参数会被忽略
为什么 $argv 里中文参数变成乱码(Windows CMD 下最明显)
根本原因是 Windows 控制台默认编码是 GBK,而 PHP 脚本文件通常是 UTF-8,$argv 直接接收 CMD 解码后的字节流,没做转码。Linux/macOS 一般无此问题(终端和 PHP 默认同为 UTF-8)。
- 临时解决:CMD 中先执行
chcp 65001切换到 UTF-8 模式,再运行脚本 - 代码层兼容:用
mb_convert_encoding($argv[1], 'UTF-8', 'GBK')(仅 Windows),但需先判断PHP_OS_FAMILY === 'Windows' - 更稳妥的做法:避免在参数中传中文,改用配置文件或环境变量传递敏感/多语言内容
参数校验和默认值怎么写才不容易出错
别依赖 isset($argv[1]) 做判断——空字符串 "" 也会让 isset 返回 true,但业务上可能算“未提供”。用 array_key_exists(1, $argv) && $argv[1] !== '' 更准;或者统一走 getopt(),它对缺失选项直接不返回键名。
- 必填参数建议在
getopt()后检查:if (!isset($options['host'])) { die("Error: --host is required\n"); } - 默认值不要硬编码在逻辑分支里,提前提取成常量或配置数组,比如:
$defaults = ['port' => 80, 'timeout' => 30]; $port = $options['port'] ?? $defaults['port']; - 注意类型转换:
$options['port']是字符串,用前记得(int)或filter_var(..., FILTER_VALIDATE_INT),否则"8080abc"也能过isset
参数解析看着简单,实际最容易栽在边界情况:空格、编码、缺失值、类型混淆。与其反复踩坑,不如早期就封装一个轻量参数解析函数,把校验、默认值、类型转换收拢起来。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











