第 23章PHPをコマンドラインから使用する

4.3以降でPHPCommand Line Interfaceを意味する CLIという名前の新しいSAPI型 (Server Application Programming Interface)をサポートします。 名前から分かるように、このSAPI型は、 PHPによるシェル(またはデスクトップ)アプリケーショ ンの開発を主な対象としています。 CLI SAPIと他のSAPIの間には、 いくつかの違いがあります。本章では、これらについて詳細を説明します。 CLICGIはその振る舞いの多くが 共通であるにもかかわらず、違うSAPIであることに留意してください。

CLI SAPIは、当初PHP 4.2.0でリ リースされましたが、この時点では実験的なステータスにあったため、 ./configureを実行する際に、明示的に --enable-cliを指定することにより、有効とする必要 がありました。PHP 4.3.0以降、 CLI SAPIはもはや実験的なステータスではなくなり、 --enable-cliはデフォルトでオンとなりました。 無効にする場合は--disable-cliを使用できます。

PHP4.3.0以降、システムにPHPがどのようにインストールされているかによって CLI/CGIバイナリの名前、位置、存在が異なります。デフォルトでは makeを実行するとCGIとCLIの両方がビルドされ ソースディレクトリのsapi/cgi/phpsapi/cli/phpにそれぞれ配置されます。両方とも phpという名前であることに注目してください。 make installでどうなるかはconfigureに因ります。 configureで例えばapxsのようなSAPIモジュールが選択された場合、または --disable-cgiが指定された場合、 make installによってCLIが{PREFIX}/bin/php にコピーされます。さもなければCGIがそこにコピーされます。 既にインストールされているCGIバイナリを上書きしたい場合には、 make installの後にmake install-cli を実行してください。あるいはconfigureで--disable-cgi を指定しておくこともできます。

注意: --enable-cli--enable-cgiの両方が デフォルトで有効になっているため、configureで--enable-cli をconfigureで指定しなくても必然的にmake installで CLIが{PREFIX}/bin/phpとしてコピーされます。

PHP4.2.0からPHP4.2.3までのWindowsパッケージではCLIは CGI php.exeと同じフォルダに php-cli.exeとして配布されていました。 PHP4.3.0からはWindowsパッケージではCLIはcliという 別のフォルダにphp.exeとして配布されます。 したがってcli/php.exeとなります。

自分のSAPIは何か?: シェルでphp -vをタイプすると、 phpがCGIなのかCLIなのかわかります。 php_sapi_name()と定数PHP_SAPI も参照してください。

注意: unixのmanualページがPHP4.3.2で追加されました。 シェル環境からman phpすることで見ることができます。

CLI SAPIを他のSAPIと比べた時 の大きな違いを以下に示します。

PHPバイナリにより提供されるコマンドラインオプショ ンの一覧は、-hスイッチを指定して PHPを実行することによりいつでも調べることができ ます。
Usage: php [options] [-f] <file> [args...]
       php [options] -r <code> [args...]
       php [options] [-- args...]
  -s               Display colour syntax highlighted source.
  -w               Display source with stripped comments and whitespace.
  -f <file>        Parse <file>.
  -v               Version number
  -c <path>|<file> Look for php.ini file in this directory
  -a               Run interactively
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -z <file>        Load Zend extension <file>.
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -i               PHP information
  -r <code>        Run PHP <code> without using script tags <?..?>
  -h               This help

  args...          Arguments passed to script. Use -- args when first argument 
                   starts with - or script is read from stdin

CLI SAPIは、実行するPHPコード を取得するために三種類の異なる手段をサポートしています。

  1. PHPに特定のファイルの実行を指示する。

    php my_script.php
    
    php -f my_script.php
    上記の方法は共に(-fスイッチの使用の如何に関ら ず)指定したファイルmy_script.phpを実行しま す。実行ファイルとしてあらゆるファイルを指定することができ、 PHPスクリプトは拡張子 .phpで終わる必要がなく、任意の名前や拡張子 を使用することができます。

  2. 実行するPHPコードをコマンドラインで直接指定する。

    php -r 'print_r(get_defined_constants());'
    シェル変数の置換と引用符の使用については特に注意して下さい。

    注意: この例をよくみて下さい。開始/終了タグがありません! -rスイッチを使用した場合、これらのタグは不要 となります。これらのタグを使用するとパーサエラーを発生します。

  3. 実行するPHPコードを標準入力 (stdin)で指定する。

    これは強力な機能で、以下の(仮想的な)例に示すように、動的に PHPコードを生成し、実行バイナリに入力すること ができます。
    $ some_application | some_filter | php | sort -u >final_output.txt

これらのコードを実行する三種類の方法を組み合わせて使用することはで きません。

他のシェルアプリケーションのように、PHPバイナリ に引数を指定することができるだけでなく、PHPスク リプトがこの引数を取得することも可能です。スクリプトに指定できる引 数の数はPHPによる制限を受けません。 (シェルは指定可能な文字数の最大値を設定しています。通常、この制限値 を越えることはできません。) スクリプトに指定した引数は、グローバル 配列$argvでアクセス可能です。 添字0は、常にスクリプト名が含まれています。 ( PHPコードが標準入力またはコマンドラインスイッ チ-rにより指定された場合、スクリプト名は -となります。) 登録される第2のグローバル変数は$argcで、 (スクリプトに指定された引数の数ではなく 、)配列$argvの要素数が含まれます。

スクリプトに指定する引数が文字-で始まっていない 限り、特に留意すべきことはありません。スクリプトに指定する引数が文 字-で始まる場合、PHP自体がこ れをパースする必要があるとみなすため、問題を発生します。 これを防止するため、引数リストセパレータ--を使用 して下さい。PHPにパースされる引数の後に このセパレータを置くと、その後の全ての引数はそのままパースされずに スクリプトに渡されます。

# This will not execute the given code but will show the PHP usage
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]

# This will pass the '-h' argument to your script and prevent PHP from showing it's usage
$ php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}

また、PHPをシェルスクリプトとして使用する他の 手段があります。最初の行が#!/usr/bin/phpで始まり、 PHPの開始/終了タグの中に通常の PHPコードが続くスクリプトを書き、適当なファイル 実行属性を設定する(e.g. chmod +x test)ことが可能です。 この方法は、通常のシェル/Perlスクリプトと同様に実行することができます。
#!/usr/bin/php
<?php
    var_dump
($argv);
?>
このファイルの名前がtestで、カレントディレクト リにあるとすると、以下のように実行することができます。
$ chmod 755 test
$ ./test -h -- foo
array(4) {
  [0]=>
  string(6) "./test"
  [1]=>
  string(2) "-h"
  [2]=>
  string(2) "--"
  [3]=>
  string(3) "foo"
}
見て分かるように、-で始まるスクリプトのパラメー タを指定する際に、特に注意する必要はありません。

表 23-3. コマンドラインオプション

オプション説明
-s

カラー構文ハイライト表示されたソースを表示します。

このオプションは、ファイルをパースし、HTML ハイライト表示版のファイルを生成し、標準出力に書き出す内部機 構を使用します。行うのは、 <code> [...] </code>のブロック を生成することだけで、HTMLヘッダは出力され ないことに注意して下さい。

注意: このオプションは、-rオプションと同時に使 用することはできません。

-w

コメントと空白文字を削除してソースを表示します。

注意: このオプションは、-rオプションと同時に使 用することはできません。

-f

-fオプションに指定したファイル名をパースし、 実行します。このスイッチはオプションで省略することもできます。 実行するスクリプトを指定するだけで充分です。

-v

PHP, PHP SAPI, Zendのバージョンを標準出力に出力します。例:
$ php -v
PHP 4.3.0-dev (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.2.1, Copyright (c) 1998-2002 Zend Technologies

-c

このオプションを使用することにより、php.iniを探すディレクト リを指定したり、カスタマイズされたINIファ イル(php.iniという名前である必要はありません)を直接指定する ことが可能です。例:
$ php -c /custom/directory/ my_script.php

$ php -c /custom/directory/custom-file.ini my_script.php

-a

PHPを対話的に実行します。

-d

このオプションにより php.ini で指定できる設定ディレクティブ にカスタム値を設定することができます。構文は以下のようになります。
-d configuration_directive[=value]

例:
# 値の部分を省略すると、設定ディレクティブに"1"を指定します
$ php -d max_execution_time -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"

# 空の値を渡すと設定ディレクティブに""を設定します
php -d max_execution_time= -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""

# 設定ディレクティブは文字'='の後に指定したものを設定します
$  php -d max_execution_time=20 -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$  php -d max_execution_time=doesntmakesense -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "doesntmakesense"

-e

デバッガ/プロファイラ用の拡張情報を出力します。

-z

Zendエクステンションをロードします。ファイル名のみが指定された場合、 PHPはこの拡張をカレントのシステムのデフォルトライブラリパスから ロードしようとします。 (Linuxシステムの場合は/etc/ld.so.confで 指定されています) ファイル名を絶対パスで指定した場合、システムのライブラリサーチパスを 使用しません。ディレクトリ情報を有する相対ファイル名を 指定すると、PHPは、 カレントのディレクトリの相対パスから拡張モジュールをロードする ことのみを行ないます。

-l

このオプションにより、指定したPHPコードの 構文チェックのみを簡単に行なうことができます。成功した場合、 テキスト No syntax errors detected in <filename> が、標準出力に書き込まれ、リターンコードは0 となります。失敗した場合、テキスト Errors parsing <filename> に加えて、内部パーサエラーメッセージ が標準出力に書き込まれ、シェルリターンコードは、 255となります。

このオプションは、(未定義の関数のような)致命的なエラー(fatal error) はみつけません。致命的なエラーについても調べたい場合は、 -f を使用してください。

注意: このオプションは、オプション-rと共に使用することは できません。

-m

このオプションを使用すると、PHPは、PHPに組み込まれた (そしてロードされた) Zend モジュールを出力します。
$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

-i このコマンドラインオプションは、phpinfo()をコールし、 結果を出力します。PHP が正しく動作していない場合、 php -iを実行し、情報テーブルの前または中に出力 されるエラーメッセージを調べることをお勧めします。 出力は、HTML 形式で行なわれるため、かなり量が 多くなることに注意して下さい。
-r

このオプションにより、コマンドラインのみでPHP の実行ができるようになります。 PHPの開始および終了タグ (<?php および ?>) は不要で、これらを付けると パーサエラーとなります。

注意: このようにPHPを実行する際に、コマンドラインの 変数がシェルにより行なわれる置換と干渉しないように注意して下さい。

パーサエラーを生じる例
$ php -r "$foo = get_defined_constants();"
Command line code(1) : Parse error - parse error, unexpected '='
ここでの問題は、2重引用符 " を用いた場合でも sh/bashが変数置換を行うことです。 $fooはおそらく定義されていないので、 空文字列に展開された後、実行用にPHPに そのコードが渡され、以下のように読み込むことになります。
$ php -r " = get_defined_constants();"
正しい方法は、1重引用符'を使用することです。 1重引用符で括られた文字列の中の変数は、sh/bashにより展開されません。
$ php -r '$foo = get_defined_constants(); var_dump($foo);'
array(370) {
  ["E_ERROR"]=>
  int(1)
  ["E_WARNING"]=>
  int(2)
  ["E_PARSE"]=>
  int(4)
  ["E_NOTICE"]=>
  int(8)
  ["E_CORE_ERROR"]=>
  [...]
sh/bash以外のシェルを使用している場合には、別の問題を経験したことが あるかもしれません。バグレポートを作成するか phpdoc@lists.php.netにメールを送ってください。 シェル変数をコードに取得しようとしたり、エスケープを行なうために バックスラッシュを使用したりした場合にも、容易に問題を発生する 可能性があります。注意が必要です。

-h このオプションを使用すると、実際の一連のコマンドラインオプションと 各1行の説明が情報を取得できます。

PHP実行バイナリは、Webサーバから完全に独立してPHPスクリプトを実行す るために使用することができます。Unixシステムを使用している場合、実 行可能とするために、PHPスクリプトの先頭に特別な一行を追加する必要が あります。これにより、システムがそのスクリプトを実行するプログラム を知ることができます。 Windows環境では、.phpファイルのダブルクリックオ プションにphp.exeを関連づけることができます。 または、PHPによりスクリプトを実行するバッチファイルを作成することも 可能です。Unix上で動作させるためにスクリプトに追加された先頭行は、 Windows環境での動作に悪影響を与えません。このため、この手法により、 黒須プラットフォーム環境で動作するプログラムを書くことができます。 コマンドラインPHPプログラムの書方の簡単な例を以下に示します。

例 23-1. コマンドラインから実行されることを意図したスクリプト(script.php)

#!/usr/bin/php
<?php

if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
?>

This is a command line PHP script with one option.

  Usage:
  <?php echo $argv[0]; ?> <option>

  <option> can be some word you would like
  to print out. With the --help, -help, -h,
  or -? options, you can get this help.

<?php
} else {
    echo
$argv[1];
}
?>

上のスクリプトでは、特殊な先頭行が用いられており、このファイルが PHPにより実行されることを示しています。ここではCLI版を使用しているため、 HTTPヘッダは出力されません。PHPで コマンドラインアプリケーションを使用する際には、2つの変数 $argc and $argv を使用することが できます。 最初の変数は、引数の数に1(実行中のスクリプトの名前)を加えたものです。 2番目の変数は、引数を保持する配列で、スクリプト名を有する 要素0($argv[0])から始まっています。

上のプログラムでは、引数が1より少ないかまたは多いかを調べています。 また、引数が --help, -help, -h, -?の場合、 ヘルプメッセージを出力し、動的にスクリプト名を出力します。 他の引数を受け取った場合、これを出力します。

上のスクリプトをUnixで実行する場合、実行可能とした後、 script.php echothis または script.php -h とする必要があります。 Windowsでは、この処理を行なう以下のようなバッチファイルを作成することが できます。

例 23-2. コマンドラインPHPスクリプトを実行するバッチファイル(script.bat)

@c:\php\php.exe script.php %1 %2 %3 %4

上のプログラムがscript.phpという名前であると し、c:\php\php.exephp.exe があるとすると、このバッチファイルは、追加したオプション script.bat echothis または script.bat -h を指定して、スクリプトを実行します。

PHPのコマンドラインアプリケーションを拡張するために使用できる その他の関数については、拡張モジュール Readlineに関する ドキュメントも参照してください。