PHPのお勉強!

PHP TOP

対話シェル

--with-readline オプションつきで PHP をコンパイルした場合に 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 >

対話シェル上では、タブ補完機能を使って 関数や定数、クラス名、変数名、static メソッドの呼び出し、 そしてクラス定数を補完することができます。

例2 タブ補完

補完候補が複数あるときにタブキーを二度押すと、 補完候補の一覧が表示されます。

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

候補がひとつしかないときは、タブキーを一度押せば残りを補完してくれます。

php > strpt[TAB]ime(

対話シェルのセッション上で定義したものについても補完することができます。

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

対話シェル上では操作履歴が保存され、上矢印キーと下矢印キーで履歴にアクセスすることができます。 履歴の保存先は ~/.php_history ファイルです。

CLI SAPI では、二つの php.ini 設定が使えます。cli.pagercli.prompt です。cli.pager は、外部のプログラム (less など) を出力のページャとして指定することができます。 出力が画面に直接送られるかわりに、このページャに送られるようになります。 cli.prompt を指定すると、 php > プロンプトを変更することができます。

また、対話シェルの中では、 php.ini 項目を設定する際に短縮記法が使えます。

例3 対話シェル内での 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();
(出力が less に送られます)
php >

cli.prompt の設定は、次のようなエスケープシーケンスに対応しています。

cli.prompt のエスケープシーケンス
シーケンス 説明
\e プロンプトに色をつけます。たとえば \e[032m\v \e[031m\b \e[34m\> \e[0m のように使います。
\v PHP のバージョン。
\b PHP が今どのブロックにいるのかを示します。たとえば、 複数行コメントの中にいる場合は /* となります。 外側のスコープは php で表します。
\> プロンプト文字を示します。デフォルトでは > ですが、ブロックや文字列の途中にあるときは変わります。 ' " { ( > のような文字になることがあります。

注意:

auto_prepend_file および auto_append_file で インクルードされたファイルはこのモードでもパースされますが、 いくつかの制限があります。例えば、関数はそれがコールされる前に 定義されていなければなりません。

インタラクティブモード

PHP 8.1.0 より前のバージョンでは、readline 拡張モジュールが利用できない場合に、 CLI SAPI-a オプション付きで呼び出すとインタラクティブモードになっていました。 このモードでは、 完全な PHP スクリプトを標準入力(STDIN)から与えなければいけません。 スクリプトを入力後、 CTRL +D (POSIXの場合) や CTRL +Z の後に +ENTER (Windows) を続けると、その PHP スクリプトが評価されていました。 CLI SAPI-a なしで呼び出しても基本的に同じ動きをします。

PHP 8.1.0 以降では、 readline 拡張モジュールが利用できない場合、 CLI SAPI-a オプションを付けた呼び出しは失敗します。

add a note

User Contributed Notes 7 notes

up
177
Ryan P
12 years ago
Interactive Shell and Interactive Mode are not the same thing, despite the similar names and functionality.

If you type 'php -a' and get a response of 'Interactive Shell' followed by a 'php>' prompt, you have interactive shell available (PHP was compiled with readline support). If instead you get a response of 'Interactive mode enabled', you DO NOT have interactive shell available and this article does not apply to you.

You can also check 'php -m' and see if readline is listed in the output - if not, you don't have interactive shell.

Interactive mode is essentially like running php with stdin as the file input. You just type code, and when you're done (Ctrl-D), php executes whatever you typed as if it were a normal PHP (PHTML) file - hence you start in interactive mode with '<?php' in order to execute code.

Interactive shell evaluates every expression as you complete it (with ; or }), reports errors without terminating execution, and supports standard shell functionality via readline (history, tab completion, etc). It's an enhanced version of interactive mode that is ONLY available if you have the required libraries, and is an actual PHP shell that interprets everything you type as PHP code - using '<?php' will cause a parse error.

Finally, if you're running on Windows, you're probably screwed. From what I'm seeing in other comments here, you don't have readline, and without readline there is no interactive shell.
up
60
spencer at aninternetpresence dot net
13 years ago
In Windows, press Enter after your ending PHP tag and then hit Ctrl-Z to denote the end-of-file:

C:\>php -a
Interactive mode enabled

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

You can use the up and down arrows in interactive mode to recall previous code you ran.
up
14
#linuxmint-es
7 years ago
For use interactive mode enabled on GNU/Linux on distros Debian/Ubuntu/LinuxMint you must install "php*-cli" and "php*-readline" packages from official repository.
Example:
>$sudo aptitude install php5-cli php5-readline

After that you can use interactive mode.
Example:
~ $ php -a
Interactive mode enabled

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

I hope somebody help it!
up
14
Anonymous
14 years ago
Just a few more notes to add...

1) Hitting return does literally mean "execute this command". Semicolon to note end of line is still required. Meaning, doing the following will produce a parse error:

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

Whereas doing the following is just fine:

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

2) Fatal errors may eject you from the shell:

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

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

3) User defined functions are not saved in history from shell session to shell session.

4) Should be obvious, but to quit the shell, just type "quit" at the php prompt.

5) In a sense, the shell interaction can be thought of as linearly following a regular php file, except it's live and dynamic. If you define a function that you've already defined earlier in your current shell, you will receive a fatal "function already defined" error only upon entering that closing bracket. And, although "including" a toolset of custom functions or a couple of script addon php files is rather handy, should you edit those files and wish to "reinclude" it again, you'll cause a fatal "function x already defined" error.
up
2
John
6 years ago
If you delete your "~/.php_history", you MUST re-create the file manually!

Because after I deleted my history file, "php -a" (interactive mode) never saved any history anymore.

It only started working after I ran "touch ~/.php_history" to create an empty file. From then on, PHP is saving history again!

I thought this was a bit unusual. Normally, applications recreate their history files themselves. But just be aware of the fact that PHP works this way instead, guys and girls! :-)
up
2
Gray
4 years ago
When adding colours, don't forget that PHP uses the same 'readline' as Bash does, so it has the same need to wrap all colour codes in special marker characters.

If you simply add raw colour codes to the prompt, you will notice that long lines no longer get wrapped correctly -- Readline no longer knows how wide the prompt is.

To fix this, you need to start each colour code with an '0x01' byte (aka Ctrl-A aka SOH) and end it with the '0x02' byte (aka Ctrl-B aka STX). There are no escapes for these -- you have to literally put the control characters in your php-cli.ini.

For example:

<?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";
?>
up
1
turabgarip at gmail dot com
8 months ago
Note that destructors will not be triggered when exiting interactive shell by any method. (Like CTRL + D, CTRL + Z or CTRL + C).

Since the interactive shell is effectively a continuous runtime, the "end of script" condition is never met for a destructor to run. And exiting the interactive shell is not considered end of script but rather the end of interpreter process. And since the process is dead; it can't run the destructor.

Therefore the only way for a destructor to run is that you remove all the references to the corresponding object. Like:

<?php

class A {
public function
__destructor() {
// This will never run after ending PHP interactive shell session.
}
}

$a = new A();

// This is the only way for the destructor to be able to run.
$a = null; // Or;
unset($a);

?>
To Top