[英]Interactive shell using PHP
只是想知道,是否可以單獨使用 PHP 創建交互式 shell。 我的意思是像你有數據庫、python 等的東西。
如果是,如何?
是的,這是可能的。 為了具有交互性,程序必須能夠等待並讀取來自stdin 的用戶輸入。 在PHP中,你可以通過打開文件描述符從標准輸入讀取'php://stdin'
。 摘自不同問題的答案,以下是 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),你可以使用 ncurses 。
由於這個問題已經被提出和回答,一個更好的解決方案被添加到 PHP 中。 在所有最新的 PHP 版本中,您可以輕松地獲得用戶輸入,如下所示:
$input = fgets(STDIN);
我理解您的問題的方式是,您只希望 PHP 解釋器在命令行上運行,以便它評估您鍵入的任何 PHP 代碼。 我一直使用 Python 的這個特性來測試代碼片段。 在這種情況下,我相信您正在尋找的答案是執行(從命令行):
php -a
假設 PHP 在你的路徑中,這會讓你進入 PHP 解釋器,就像我的一樣:
$ php -a
Interactive shell
php >
從那里您可以開始評估任意 PHP 表達式並查看結果:
php > $a = 'abcdef';
php > echo strlen($a);
6
這是對此的擴展。 我添加了一個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);
我知道提問者不想要第二個選項,但是對於那些像我一樣想要第二個選項的人,除了phpsh
,PHP 也有它 自己的 shell :
只需運行php -a
。
由於 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
可以使用!isset
進行測試。
還有內置的readline_add_history()
將用戶輸入存儲到一個對象中,其中可以通過名稱直接檢索值(為了代碼清晰,這很好):
readline_add_history($user);
print_r(readline_list_history());
print_r(readline_user());
構建真正復雜的東西非常有用!
了解如何捕捉和發送 POSIX 信號
從您是要單獨使用 PHP 創建 shell 還是要交互式 shell 處理 PHP 命令的問題中,並不完全清楚。 我將假設后者,在這種情況下,一個例子是phpsh ,它顯然是在 Facebook 創建的,但用 python 編寫。
查看:
https://github.com/shaneharter/sheldon
很容易上手。 它包括 Symfony2 和 Zend Framework 庫,它們執行許多基本的控制台 I/O 工作,並為您提供圍繞 Command 對象(使用正則表達式路由)和 Contexts(保持不可變狀態)構建的更高級別的抽象。
我喜歡的一件事是“開箱即用”您的應用程序可以作為交互式 shell 運行,也可以作為標准腳本運行,您可以從命令行運行,指定命令,傳遞任何參數,以及當命令完成應用程序退出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.