只是想知道,是否可以单独使用PHP来创建交互式shell。我的意思是像数据库,python等一样。
如果是,怎么样?
答案 0 :(得分:38)
是的,这是可能的。为了实现交互,程序必须能够等待并读入来自 stdin 的用户输入。在PHP中,您可以通过打开'php://stdin'
的文件描述符来读取 stdin 。摘自an answer to different question,这是PHP中交互式用户提示的示例(当然,从命令行运行时):
echo "Continue? (Y/N) - ";
$stdin = fopen('php://stdin', 'r');
$response = fgetc($stdin);
if ($response != 'Y') {
echo "Aborted.\n";
exit;
}
当然,要获得完整的输入线而不是单个字符,您需要fgets()
而不是fgetc()
。根据您的程序/ shell将执行的操作,整个程序可能被构造为一个大的连续循环。希望这能让您了解如何开始。如果你想真的花哨(CLI伪GUI),你可以use ncurses。
答案 1 :(得分:24)
由于已经提出并回答了这个问题,已经为PHP添加了更好的解决方案。在所有最近的PHP版本中,您可以轻松获得用户输入:
$input = fgets(STDIN);
答案 2 :(得分:5)
我理解您的问题的方式只是希望PHP解释器在命令行上运行,以便它将评估您键入的任何PHP代码。我一直使用Python的这个功能来测试代码片段。在这种情况下,我相信你要找的答案是执行(从命令行):
php -a
假设PHP在您的路径中,这将使您进入PHP解释器,就像我的一样:
$ php -a
Interactive shell
php >
从那里开始评估任意PHP表达式并查看结果:
php > $a = 'abcdef';
php > echo strlen($a);
6
答案 3 :(得分:2)
以下是对此的扩展。我已添加isCLI()
检查,以防您在CLI和Web服务器上运行脚本。否则服务器可以使用我的函数循环。此解决方案将提示用户,检查输入,并在必要时重新提示用户输入固定输入。我rtrim()
输入,因为如果用户使用return来提交他们的条目,那么可以将其附加到条目中。验证不是必需的,只是在这种情况下不传递函数。
function isCLI() {
return (php_sapi_name() === 'cli' OR defined('STDIN'));
}
function userPrompt($message, $validator=null) {
if (!isCLI()) return null;
print($message);
$handle = fopen ('php://stdin','r');
$line = rtrim(fgets($handle), "\r\n");
if (is_callable($validator) && !call_user_func($validator, $line)) {
print("Invalid Entry.\r\n");
return userPrompt($message, $validator);
} else {
print("Continuing...\r\n");
return $line;
}
}
// Example =====================
function validateSetLangCode($str) {
return preg_match("/^[A-Z0-9]{3}-[A-Z]{2}$/", $str);
}
$code = userPrompt("Please enter the set / language codes. Use the format 'SET-EN', where SET is the three-letter set code and EN is the two-letter lang code. \r\n", 'validateSetLangCode') ?: 'SET-EN';
var_dump($code);
答案 4 :(得分:1)
关于是否要单独使用PHP创建shell,或者是否希望交互式shell处理PHP命令,这个问题并不完全清楚。我将假设后者,在这种情况下,一个例子是phpsh,显然是在Facebook上创建的,但是是用python编写的。
答案 5 :(得分:1)
我知道提问者不想要第二个选项,但对于那些想要第二个选项的人,除了phpsh
之外,PHP还有own shell:
只需运行php -a
。
答案 6 :(得分:0)
退房:
https://github.com/shaneharter/sheldon
入门很容易。它包括Symfony2和Zend Framework库,它们执行许多基本的控制台I / O工作,并为您提供围绕Command对象(带有正则表达式路由)和上下文(持有不可变状态)的更高级别的抽象。
我喜欢的一件事是“开箱即用”您的应用程序既可以作为交互式shell运行,也可以作为可以从命令行运行的标准脚本运行,指定命令,传递任何参数,以及命令完成后,应用程序退出。
答案 7 :(得分:0)
由于PHP有一个内置的 unix only 函数readline()
来完成这个,所以留下以下注释。
我们可以使用readline
的结果并将其保存到var。
#!/usr/bin/php
<?php
$user = readline("List dir [l] | Say hello [h] | exit [q]: ");
if ($user === "l"){ system("ls"); }
if ($user === "h"){ echo "Hello!"; }
if ($user === "q"){ exit; }
echo "\nThanks!";
示例输出:
l
ls结果
h
«你好»
q
退出
ctrl+c
退出。
ctrl+d
,继续下一个序列。 “谢谢”。 $user
已定义且为空,无错误。
ctrl+d
有一些输入:没有动作。还在等待输入。
ctrl+m
继续并获取$user
中的当前输入。
ctrl+j
继续并采用$user
中的当前输入,行为与ctrl+m
相同。
Return
继续下一个序列«谢谢»。 $user
可以保持空白,没有错误。
ctrl+z
可用于取消循环并移至顶部循环。如果未在此范围中定义var,则将取消设置$user
。
根据输入,我们可以使用!empty
定义空值或进行更多手术测试(readline响应可以是多个字符)。
$user
对{p> !isset
进行测试。
还有内置的readline_add_history()
将用户输入存储到对象中,其中的值可以通过名称直接检索(Nice代码清晰度):
readline_add_history($user);
print_r(readline_list_history());
print_r(readline_user());
构建真正复杂的东西非常有用!