PHP Conference Japan 2024

互動式介面

如果 PHP 使用 --with-readline 選項編譯,則 CLI SAPI 可以透過 -a 選項提供互動式介面。從 PHP 7.1.0 開始,如果啟用了 readline 擴充套件,互動式介面也適用於 Windows。

使用互動式介面,您可以直接輸入 PHP 程式碼並執行。

範例 #1 使用互動式介面執行程式碼

$ php -a
Interactive shell

php > echo 5+8;
13
php > function addTwo($n)
php > {
php { return $n + 2;
php { }
php > var_dump(addtwo(2));
int(4)
php >

互動式介面還提供函式、常數、類別名稱、變數、靜態方法呼叫和類別常數的 Tab 鍵自動完成。

範例 #2 Tab 鍵自動完成

當有多個可能的完成選項時,按下 Tab 鍵兩次將會顯示這些完成選項的列表

php > strp[TAB][TAB]
strpbrk   strpos    strptime  
php > strp

當只有一個可能的完成選項時,按下 Tab 鍵一次將會在同一行完成剩餘的部分

php > strpt[TAB]ime(

自動完成也適用於在目前互動式介面工作階段中定義的名稱

php > $fooThisIsAReallyLongVariableName = 42;
php > $foo[TAB]ThisIsAReallyLongVariableName

互動式 Shell 會儲存您的歷史紀錄,您可以使用向上和向下鍵來存取。歷史紀錄儲存在 ~/.php_history 檔案中。

CLI SAPI 提供了 php.ini 設定 cli.pagercli.promptcli.pager 設定允許外部程式(例如 less)作為輸出的分頁器,而不是直接顯示在螢幕上。 cli.prompt 設定可以更改 php > 提示符。

也可以在互動式 Shell 中使用簡寫符號設定 php.ini 設定。

範例 #3 在互動式 Shell 中設定 php.ini 設定

cli.prompt 設定

php > #cli.prompt=hello world :> 
hello world :>

使用反引號可以在提示符中執行 PHP 程式碼

php > #cli.prompt=`echo date('H:i:s');` php > 
15:49:35 php > echo 'hi';
hi
15:49:43 php > sleep(2);
15:49:45 php >

將分頁器設定為 less

php > #cli.pager=less
php > phpinfo();
(output displayed in less)
php >

cli.prompt 設定支援一些跳脫序列

cli.prompt 跳脫序列
序列 說明
\e 用於為提示符添加顏色。例如 \e[032m\v \e[031m\b \e[34m\> \e[0m
\v PHP 版本。
\b 指示 PHP 所在的程式碼區塊。例如,/* 表示在多行註釋內。外部作用域以 php 表示。
\> 指示提示字元。預設情況下為 >,但在 Shell 處於未結束的程式碼區塊或字串內時會更改。可能的字元有:' " { ( >

注意事項:

透過 auto_prepend_fileauto_append_file 包含的檔案會在此模式下解析,但有一些限制 - 例如,函式必須在呼叫之前定義。

互動模式

如果沒有 readline 擴充功能,在 PHP 8.1.0 之前,使用 -a 選項呼叫 CLI SAPI 會提供互動模式。在此模式下,應該透過 STDIN 提供完整的 PHP 指令碼,並在使用 CTRL +D (POSIX) 或 CTRL +Z 後加上 ENTER (Windows) 結束後,會評估此指令碼。這基本上與不使用 -a 選項呼叫 CLI SAPI 相同。

從 PHP 8.1.0 開始,如果沒有 readline 擴充功能,使用 -a 選項呼叫 CLI SAPI 將會失敗。

新增註解

使用者貢獻的註解 7 則註解

Ryan P
12 年前
互動式 Shell 和互動模式並非相同,儘管名稱和功能相似。

如果您輸入 `php -a` 後,看到 `Interactive Shell` 的回應,接著出現 `php>` 提示符號,表示您具備交互式 Shell 功能(PHP 編譯時包含了 readline 支援)。反之,如果您看到的回應是 `Interactive mode enabled`,則表示您**沒有**交互式 Shell 功能,本文內容對您不適用。

您也可以檢查 `php -m` 的輸出,看看是否有列出 readline;如果沒有,就表示您沒有交互式 Shell。

交互模式基本上就像使用標準輸入 (stdin) 作為檔案輸入來執行 PHP。您只需輸入程式碼,完成後(按下 Ctrl-D),PHP 就會執行您輸入的內容,如同執行一般的 PHP (PHTML) 檔案一樣;因此,您需要以 `<?php` 開頭,才能在交互模式中執行程式碼。

交互式 Shell 會在您輸入完成每個表達式時(以 `;` 或 `}` 結尾)立即進行評估,並在不終止執行的情況下回報錯誤,同時透過 readline 支援標準 Shell 功能(例如:歷史紀錄、Tab 鍵自動完成等)。它是交互模式的增強版本,**僅**在您具備必要的函式庫時才可用,並且是一個真正的 PHP Shell,會將您輸入的所有內容都解讀為 PHP 程式碼;使用 `<?php` 會造成語法錯誤。

最後,如果您使用的是 Windows 系統,那您可能就沒轍了。從我看到的其他評論來看,Windows 系統上沒有 readline,而沒有 readline 就沒有交互式 Shell。
spencer at aninternetpresence dot net
13 年前
在 Windows 系統中,請在 PHP 結束標籤後按下 Enter 鍵,然後按下 Ctrl-Z 表示檔案結束。

C:\>php -a
Interactive mode enabled

<?php
echo "Hello, world!";
?>
^Z
Hello, world!

在交互模式中,您可以使用向上和向下箭頭鍵來回顧先前執行的程式碼。
#linuxmint-es
7 年前
要在 GNU/Linux 的 Debian/Ubuntu/LinuxMint 等發行版上使用交互模式,您必須從官方軟體庫安裝 `php*-cli` 和 `php*-readline` 套件。
範例
>$sudo aptitude install php5-cli php5-readline

之後,您就可以使用交互模式了。
範例
~ $ php -a
Interactive mode enabled

php >echo "hola mundo!\n";
hola mundo!
php >

希望這對大家有幫助!
匿名
14 年前
再補充幾點說明…

1) 按下 Enter 鍵的字面意義是「執行此命令」。表示行尾的分號仍然是必需的。也就是說,執行以下程式碼會產生語法錯誤:

php > print "test"
php > print "asdf";

而執行以下程式碼則沒有問題:

php > print "test"
php > ."asdf";

2) 致命錯誤可能會導致您退出 Shell。

name@local:~$ php -a
php > asdf();

Fatal Error: call to undefined function...
name@local:~$

3) 使用者自訂函式不會在 Shell 工作階段之間儲存於歷史紀錄中。

4) 這應該很明顯,但要退出 Shell,只需在 php 提示符號下輸入 "quit" 即可。

5) 從某種意義上來說,Shell 的互動可以被認為是線性地執行一個普通的 php 檔案,只是它是即時且動態的。如果您在目前的 Shell 中重新定義一個先前已定義的函式,則只有在輸入右括號 `}` 時才會收到「函式已定義」的致命錯誤。此外,雖然「include」一套自訂函式或幾個附加的 php 指令碼檔案相當方便,但如果您編輯了這些檔案並希望再次「include」它們,則會導致「函式 x 已定義」的致命錯誤。
John
6 年前
如果您刪除了 `~/.php_history` 檔案,您**必須**手動重新建立該檔案!

因為在我刪除歷史紀錄檔案後,`php -a`(交互模式)就再也不儲存任何歷史紀錄了。

在我執行 "touch ~/.php_history" 建立一個空檔案後,它才開始運作。從那時起,PHP 又開始儲存歷史記錄了!

我覺得這有點不尋常。一般來說,應用程式會自行重建它們的歷史記錄檔。但各位,請注意 PHP 就是這樣運作的! :-)
Gray
4 年前
新增顏色時,別忘了 PHP 使用與 Bash 相同的「readline」,因此它同樣需要將所有顏色代碼用特殊的標記字元包起來。

如果你只是在提示符中加入原始顏色代碼,你會發現長行不再正確換行 ── Readline 不再知道提示符的寬度。

要解決這個問題,你需要用 '0x01' 位元組(也就是 Ctrl-A 或 SOH)開始每個顏色代碼,並以 '0x02' 位元組(也就是 Ctrl-B 或 STX)結束。這些沒有跳脫字元 ── 你必須在 php-cli.ini 中直接放入控制字元。

例如

<?php

// cli.prompt = <SOH>\e[1m<STX> PHP! \> <SOH>\e[m<STX>

echo "cli.prompt = \x01\\e[1m\x02 PHP! \x01\\e[m\x02\n";
?>
turabgarip at gmail dot com
7 個月前
請注意,使用任何方法(例如 CTRL + D、CTRL + Z 或 CTRL + C)退出互動式 shell 時,解構函式將不會被觸發。

由於互動式 shell 實際上是一個連續的運行環境,「腳本結束」條件永遠不會滿足解構函式的運行。而退出互動式 shell 並不被視為腳本結束,而是直譯器程序的結束。由於程序已終止,它無法運行解構函式。

因此,要讓解構函式運行,唯一的方法是移除所有對應物件的參考。例如

<?php

class A {
public function
__destructor() {
// 結束 PHP 互動式 shell 階段作業後,這段程式碼永遠不會執行。
}
}

$a = new A();

// 這是讓解構函式能夠執行的唯一方法。
$a = null; // 或者;
unset($a);

?>
To Top