PHP作为一门web开发语言,相对来说,命令行程序并不是它的主战场。那么多年轻的PHP开发者可能连命令行脚本都没有写过,更别说交互命令操作了。今天我们带来的扩展是PHP的交互式命令行操作。readline扩展函数实现了GNUReadline库的接口。这些函数提供了一个可编辑的命令行。一个示例是Bash,它允许您使用箭头键插入字符或滚动命令历史记录。由于库的交互特性,此功能在您编写的Web应用程序中用处不大,但在您编写在命令行上使用的脚本时非常有用。安装Readline扩展PHP官方安装包中已经添加了Readline扩展。如果是新的PHP环境,编译时加上--with-readline即可。另外,我们还需要安装操作系统的Readline库。当然,如果PHP已经正常运行,你也可以重新编译。#yuminstall-yreadline-devel#./congiurexxxx--with-readline默认情况下,如果编译时不加--whit-readline,也可以使用Readline的一些函数,只是调用了系统libedit库.某些函数,例如readline_list_history(),不能使用。如果想充分使用Readline的扩展能力,还需要安装操作系统的libreadline库(上面yum安装的readline-devel),并在PHP中编译安装相应的参数。基本功能操作Readline扩展提供的功能很少,但也非常简单易用。读取一行$line=readline("请输入命令:");//读取命令行交互信息echo$line,PHP_EOL;//aaaPHP代码运行后,我们进入命令提示符等待状态,会提示“请输入命令:”,当我们输入aaa并回车时,输入的内容保存在$line变量中。命令历史列表相关操作Readline最强大的功能之一是它自带一组命令历史记录。但这需要我们手动将命令添加到命令历史记录中。$line=readline("请输入命令:");//读取命令行交互信息if(!empty($line)){readline_add_history($line);//需要手动添加到命令历史记录中}echo$line,PHP_EOL;//aaa$line=readline("请输入命令:");if(!empty($line)){readline_add_history($line);}//命令历史列表print_r(readline_list_history());//Array//(//[0]=>aaa//[1]=>bbb//)使用readline_add_history()函数向命令历史添加一个命令,然后使用readline_list_history()打印出一个记录我们之前在交互环境中发送的命令。当然,如果只是这么简单的保存打印就没意思了。它还可以将这些历史信息保存到外部文件中进行存储。//将历史命令写入文件//Array//(//)//从文件读取命令历史readline_read_history('./readline_history');print_r(readline_list_history());//Array//(//[0]=>bbb//[1]=>bbb//)我们使用readline_write_history()函数将当前命令历史记录保存到一个文件中,然后使用readline_clear_history()清除当前命令历史列表的内容,此时打印Therenothinginreadline_list_history()的话。然后,我们使用readline_read_history()从文件中加载命令历史记录以进行恢复。这组函数是不是很有趣?我们可以记录客户所有的命令操作,无论是安全审查还是事件回放,都非常有用。查看Readline状态//当前命令行内部的变量信息print_r(readline_info());//Array//(//[line_buffer]=>bbb//[point]=>3//[end]=>3//[mark]=>0//[done]=>1//[pending_input]=>0//[prompt]=>请输入命令://[terminal_name]=>xterm-256color//[completion_append_character]=>//[completion_suppress_append]=>//[library_version]=>7.0//[readline_name]=>other//[attempted_completion_over]=>0//)readline_info()函数比较简单,大家可以看最后的交互命令的信息包括命令输入的内容line_buffer、内容长度点、提示信息提示等。命令提示符作用在Linux等操作系统上,如果我们记不住命令的全拼也没关系,只要记住它的前几个字符,按两个Tab键就可以得到相关的命令提示符。当然,Readline扩展库也为我们准备了这样的功能。//类似命令行按Tab键的提示效果readline_completion_function(function($input,$index){$commands=['next','exit','quit'];$matches=[];if($input){//如果命令中包含关键字,则提示命令信息foreach($commandsas$c){if(strpos($c,$input)!==false){$matches[]=$c;}}}else{$matches=$commands;}return$matches;});//使用Tab键测试$line=trim(readline("请输入命令:"));if(!empty($line)){readline_add_history($line);}echo$line,PHP_EOL;//当前输入的命令信息//如果命令是exit或者quit,退出程序执行if($line=='exit'||$line=='quit'){exit;}readline_completion_function()函数会接收回调函数。在交互式命令行模式下,即调用readline函数时,按下Tab键时,会进入该函数中的回调函数。\$input为当前输入内容的值,$index为字符数。我们在这个回调函数中定义了几个默认命令。当您键入n并直接按Tab键时,程序将提示完成下一个命令。当然也可以通过这个$matches数组返回呈现多个以相同字母开头的item。此外,在此代码中,如果我们键入exit或quit。将退出运行该程序。字符回调操作相关实例最后几个函数我们将通过一个复杂的小测试来学习。//输出内容进入这个回调函数functionrl_callback($ret){global$c,$prompting;echo"您输入的内容是:$ret\n";$c++;readline_add_history($ret);//Limiting会调用10次,也可以通过命令行的输入内容来判断,比如上面的exit就是exitif($c>10){$prompting=false;//删除最后安装的回调函数句柄并恢复终端设置readline_callback_handler_remove();}else{//继续递归回调readline_callback_handler_install("[$c]entersomething:",'rl_callback');}}$c=1;$提示=真;//初始化一个readline回调接口,然后终端输出提示信息并立即返回。需要等待readline_callback_read_char()函数被调用后才能进入回调函数。readline_callback_handler_install("[$c]Whattoenter:",'rl_callback');//当$prompting为真时,等待输入信息while($prompting){$w=null;$e=空;$r=数组(标准输入);$n=stream_select($r,$w,$e,null);if($n&&in_array(STDIN,$r)){//当接收到一行时,读取一个字符,通知readline调用回调函数readline_callback_read_char();}}echo"结束,所有输入完成!\n";//[1]Entersomething:A//Yourinputis:A//[2]Inputsomething:B//Yourinputis:B//[3]什么是输入:C//什么是输入:C//[4]什么是输入:D//什么是输入:D//[5]什么是输入:E//您输入的内容是:E//[6]输入的内容:F//您输入的内容是:F//[7]输入的内容:G//您输入的内容是:G//[8]Entersomething:H//Yourinputis:H//[9]Inputsomething:I//Yourinputis:I//[10]Inputsomething:J//Whatyoutypedis:J//End,所有输入完成!print_r(readline_list_history());//数组//(//[0]=>A//[1]=>B//[2]=>C//[3]=>D//[4]=>E//[5]=>F//[6]=>G//[7]=>H//[8]=>I//[9]=>J//)首先,我们开始先不管上面的自定义函数,直接往下看readline_callback_read_char()。它的作用是接收到一行时读取一个字符,通知readline调用回调函数。即当一行输入完成并回车时,该函数会通知Readline组件调用readline_callback_handler_install()注册的回调函数。readline_callback_handler_install()函数的作用是初始化一个readline回调接口,然后终端输出提示信息并立即返回。如果回调函数中没有任何操作,则该函数只是输出提示并结束。在我们例子的回调函数rl_callback()中,我们根据当前接收到的命令数判断,如果接收到的命令在十次以内,则继续接收命令,直到第十次调用readline_callback_handler_remove()去除命令之前的readline_callback_handler_install()安装回调并恢复终端的默认设置。最终执行的结果就是注释中的内容。您也可以复制代码并自己运行调试。只有自己调试过才能理解的更深刻。总结Readline功能强大,作为默认PHP安装附带的扩展。通常,默认添加的扩展都是经过时间考验且非常有用的扩展。大家可以根据这些内容进行更深入的学习,并将其应用到实战中。测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/202006/source/PHP%E7%9A%84%E5%91%BD%E4%BB%A4%E8%A1%8C%E6%89%A9%E5%B1%95Readline%E7%9B%B8%E5%85%B3%E5%87%BD%E6%95%B0%E5%AD%A6%E4%B9%A0.php参考文档:https://www.php.net/manual/zh/book.readline.phphttps://www.php.cn/php-weizijiaocheng-339883.html===========各媒体平台均可搜索【硬核项目经理】
