PHP的命令行模式
自从PHP4.3.0开始,PHP提供了CLI(Command Line Interface)命令行接口,CLI SAPI模块主要用于PHP外壳应用的开发。
区别于CGI(Common Gateway Interface),CLI有很多不同的特性:
与 CGI SAPI 不同,CLI输出没有任何头信息
在运行时,CLI不会把工作目录改为脚本的当前目录
出错时CLI输出纯文本的错误信息(非 HTML 格式)
CLI SAPI 强制覆盖了 php.ini 中的某些设置,因为这些设置在命令行没有意义,下面设置在CLI强制覆盖
html_errors: false,取消HTML错误信息
implicit_flush: true,print和echo的输出会立即写到输出端,而不做任何缓冲,可使用
output buffering
实现输出缓冲
max_execution_time: 0,命令行运行的php脚本可能等待输入等,运行时间可能很长
register_argc_argv: true,总是可以在命令行模式下访问命令行参数
CLI可以独立于Web Server运行
PHP获取命令行参数的方法
访问全局变量
$argv
,
$argc
在PHP的命令行模式下,可在脚本中直接访问
$argv
,
$argc
两个全局变量:
$argv: 命令行实际参数的数组
$argc: 命令行参数的个数
比如现在有一个
arg_test.php
的文件:
var_dump(
argc);
var_dump(
argv);
在命令行以下面的命令启动:
php arg_test.php -t 800 a set
,输出如下:
int(5)
array(5) {
string(12) "arg_test.php"
string(2) "-t"
string(3) "800"
string(1) "a"
string(4) "bset"
一个空格区分一个参数,包括当前的脚本名称,都会放在$argv中,当时这种方式不便于处理-t这样的参数,需要自己进行解析。
PHPgetopt参数处理函数
getopt函数是PHP自带专门用来处理复杂命令行参数的内置函数。原型如下:
getopt ( string options [, arraylongopts [, int &$optind ]] ) : array
关于getopt()的说明如下:
options: 该字符串中的每个字符会被当做选项字符,匹配以单个连字符(-)传入到脚本的选项,比如x识别-x选项,只允许a-z,A-Z,0-9
longopts: 选项数组,每个数组元素会被作为选项字符串,匹配了以两个连字符(–)传入到脚本的选项,比如opt识别--opt
optind(>=PHP7.1.0): 如果存在该参数,那么参数解析停止的索引将写入该变量
options字符串可能包含一下元素:
单独的字符(不接受值)
后面跟随冒号的字符(此选项需要值)
后面跟随两个冒号的字符(此选项的值可选)
选项的值是字符串后的第一个参数,值和选项之间可以没有前置空格,选项值中不可以包含空格。
getopt()示例和用法
基本用法示例,PHP文件arg_test.php如下:
options = getopt('a:b:cde');
var_dump(options);
以下面的命令启动:
php arg_test.php -aav -c -d -b bv -f
则输出为:
array(4) {
["a"]=>
string(2) "av"
["c"]=>
bool(false)
["d"]=>
bool(false)
["b"]=>
string(2) "bv"
可以注意到使用getopt(options)时的几个点:
options中的参数顺序和命令行的参数顺序不用相同
选项和值之间是否有空格都能区分值
options中单独的字符,返回的参数列表的key是选项,value是false
options中没有指定的选项,及时命令行传入,也不会返回
长选项示例,arg_test.php:
// Script arg_test.php
shortopts = "";shortopts .= "f:"; // Required value
shortopts .= "v::"; // Optional valueshortopts .= "abc"; // These options do not accept values
longopts = array(
"required:", // Required value
"optional::", // Optional value
"option", // No value
"opt", // No value
);options = getopt(shortopts,longopts);
var_dump($options);
以下面命令启动:
php arg_test.php -f "value for f" -v -a --required value --optional="optional value" --option
array(6) {
["f"]=>
string(11) "value for f"
["v"]=>
bool(false)
["a"]=>
bool(false)
["required"]=>
string(5) "value"
["optional"]=>
string(14) "optional value"
["option"]=>
bool(false)
同一个选项可以传递多次,并且可以合并不同的选项:
// Script arg_test.php
options = getopt("abc");
var_dump(options);
以下面的命令启动:
php arg_test.php -aaac
输出结果为:
array(2) {
["a"]=>
array(3) {
bool(false)
bool(false)
bool(false)
["c"]=>
bool(false)
最后是使用optind的例子,注意optind选项需要PHP7.1以上才支持:
// Script arg_test.php
optind = null; // 需要预先定义optind
opts = getopt('a:b:', [],optind);
var_dump(optind);pos_args = array_slice(argv,optind);
var_dump($pos_args);
以下面的命令启动:
php arg_test.php -a 1 -b 2 -- test
输出如下:
int(6)
array(1) {
string(4) "test"
注意上面的命令:php arg_test.php -a 1 -b 2 -- test中一共有6个参数,--和test是两个参数。
命令行输入和输出
有的时候,我们需要在PHP脚本中检测用户的输入,以及输出一些提示信息给用户。这就需要用到PHP定义的标准输入输出流:
STDIN: 一个已打开的指向stdin的流
STDOUT: 一个已打开的指向stdout的流
STDERR: 一个已打开的指向stderr的流
可以像操作文件句柄一样操作这些标准流,而且不需要手动关闭,PHP会自行关闭。可以发现PHP对这三个常量的定义如下:
define(‘STDIN’, fopen(‘php://stdin’, ‘r’));
define(‘STDOUT’, fopen(‘php://stdout’, ‘w’));
define(‘STDERR’, fopen(‘php://stderr’, ‘w’));
显然这三个常量已经是打开的文件句柄,可以直接进行操作,下面是一个实例:
// 像写入文件一样,将内容显示到控制台
fwrite(STDOUT, 'please input a number between 1 and 10: ');
input = fgets(STDIN); // 从控制台读取输入continue = true;
// 轮询输入,知道正确为止
while (continue) {
if (input < 1 || input>10) {
// 输出到错误流
fwrite(STDERR, 'you input number is wrong: ' .input);
} else {
fwrite(STDOUT, 'you input number is correct: ' . input);continue = false;
$input = fgets(STDIN); // 从控制台读取输入
交互过程如下,其中输出到STDERR的内容会标红显示:
please input a number between 1 and 10: 12
you input number is wrong: 12
you input number is wrong: 34
you input number is correct: 9
Process finished with exit code 0
PHP CLI的可行参数
PHP的命令行模式另外还提供了很多参数来控制CLI的行为,这些参数必须紧跟在php命令后面。
# 指定php.ini配置文件运行
php -c ./custom-php.ini my_script.php
下面列出几个常用的参数,详细的参数可参考官网文档。