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

4.3 以降で PHP は Command 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 によりこれを無効とする ことも可能です。

PHP 4.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 を指定したからといって、make install{PREFIX}/bin/php にコピーされるのが必ずしも CLI になるとは限りません。

PHP 4.2.0 から PHP 4.2.3 までの Windows パッケージでは CLI は CGI php.exe と同じフォルダに php-cli.exe として配布されていました。 PHP 4.3.0 からは Windows パッケージでは CLI は cli という 別のフォルダに php.exe として配布されます。 したがって cli/php.exe となります。 PHP 5 以降、CLI はメインフォルダ内で php.exe という名前で配布されます。CGI バージョンは、php-cgi.exe として配布されます。

PHP 5 では、新しく php-win.exe というファイルが 配布されます。これは CLI バージョンとほぼ同じですが、php-win は何も 出力しないため、コンソールを必要としません(画面に「DOS 窓」が表示 されません)。この振る舞いは、php-gtk と似ています。このためには --enable-cli-win32 オプションを 含めて configure を行います。

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

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

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

PHP バイナリにより提供されるコマンドラインオプションの一覧は、 -h スイッチを指定して PHP を実行することにより いつでも調べることができます。

Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

  -a               Run interactively
  -c <path>|<file> Look for php.ini file in this directory
  -n               No php.ini file will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f <file>        Parse and execute <file>.
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r <code>        Run PHP <code> without using script tags <?..?>
  -B <begin_code>  Run PHP <begin_code> before processing input lines
  -R <code>        Run PHP <code> for every input line
  -F <file>        Parse and execute <file> for every input line
  -E <end_code>    Run PHP <end_code> after processing all input lines
  -H               Hide any passed arguments from external tools.
  -s               Display colour syntax highlighted source.
  -v               Version number
  -w               Display source with stripped comments and whitespace.
  -z <file>        Load Zend extension <file>.

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

  --ini            Show configuration file names

  --rf <name>      Show information about function <name>.
  --rc <name>      Show information about class <name>.
  --re <name>      Show information about extension <name>.
  --ri <name>      Show configuration for extension <name>.

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 にパースされる引数の後に このセパレータを置くと、その後の全ての引数はそのままパースされずに スクリプトに渡されます。

# これは、指定したコードを実行せずに PHP の使用法を示します
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]

# これは '-h' を引数として解釈し、PHP の使用法を表示しません
$ php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}

また、PHP をシェルスクリプトとして使用する他の手段があります。 最初の行が #!/usr/bin/php で始まり、 PHP の開始/終了タグの中に通常の PHP コードが続くスクリプトを書き、適当なファイル 実行属性を設定する(例: chmod +x test)ことが可能です。 この方法は、通常のシェル/Perl スクリプトと同様に実行することができます。

例 43-1. シェルスクリプトとしての PHP スクリプトの実行

#!/usr/bin/php
<?php
var_dump
($argv);
?>

このファイルの名前が test で、カレントディレクトリに あるとすると、以下のように実行することができます。

$ chmod +x test
$ ./test -h -- foo
array(4) {
  [0]=>
  string(6) "./test"
  [1]=>
  string(2) "-h"
  [2]=>
  string(2) "--"
  [3]=>
  string(3) "foo"
}

見て分かるように、- で始まるスクリプトのパラメータを 指定する際に、特に注意する必要はありません。

長いオプション指定は、PHP 4.3.3 以降で利用可能です。

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

オプション長いオプション説明
-a--interactive

PHP を対話的に実行します。PHP のコンパイル時に Readline 拡張モジュール(Windows 版では利用できません)を含めた場合、補完(例: 変数名の一部を 入力して TAB キーを押すと、PHP が完全な変数名に変換する)・ 矢印キーによるコマンド履歴 などの高度な機能が利用できます。コマンドの履歴は ~/.php_history ファイルに保存されます。

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

注意: オートローディング は、PHP を CLI 対話シェルで実行している場合は使用できません。

-c--php-ini

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

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

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

このオプションを指定しない場合、ファイルは、 デフォルトの位置 で探索されます。

-n--no-php-ini

php.ini を完全に無視します。このスイッチは、PHP 4.3.0 以降で 利用可能です。

-d--define

このオプションにより 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--profile-info

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

-f--file

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

-h と -?--help と --usage このオプションを使用すると、実際の一連のコマンドラインオプションと 各1行の説明が情報を取得できます。
-i--info このコマンドラインオプションは、phpinfo() をコールし、 結果を出力します。PHP が正しく動作していない場合、 php -i を実行し、情報テーブルの前または中に 出力されるエラーメッセージを調べることをお勧めします。 出力は、HTML 形式で行なわれるため、かなり 量が多くなることに注意してください。
-l--syntax-check

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

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

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

-m--modules

このオプションを使用すると、PHP に組み込まれた (そしてロードされた) Zend モジュールを出力します。

$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

-r--run

このオプションにより、コマンドラインのみで 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 以外のシェルを使用している場合には、別の問題を経験したことが あるかもしれません。バグを http://bugs.php.net/ に報告してください。 シェル変数をコードに取得しようとしたり、エスケープを行なうために バックスラッシュを使用したりした場合にも、容易に問題を発生する 可能性があります。注意が必要です。

注意: -rCLI SAPI で有効で、CGI SAPI では使用できません。

注意: このオプションはあくまで基本的な機能を提供するものです。そのため、 いくつかの設定ディレクティブ(例: auto_prepend_file および auto_append_file)は このモードでは無視されます。

-B--process-begin

標準入力を処理する前に実行する PHP コードを指定します。 PHP 5 で追加されました。

-R--process-code

それぞれの入力行に対して実行する PHP コードを指定します。 PHP 5 で追加されました。

このモードには 2 つの特別な変数 $argn$argi が用意されています。 $argn は PHP がその瞬間に処理している行を含み、 $argi はその行番号を含んでいます。

-F--process-file

全ての入力行に対して実行する PHP ファイルを指定します。 PHP 5 で追加されました。

-E--process-end

入力を処理した後に実行する PHP コードを指定します。 PHP 5 で追加されました。

例 43-2. とあるプロジェクトの行数をカウントするための -B, -R そして -E オプションの使用例

$ find my_proj | php -B '$l=0;' -R '$l += count(@file($argn));' -E 'echo "Total Lines: $l\n";'
Total Lines: 37328

-s--syntax-highlight と --syntax-highlight

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

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

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

-v--version

PHP, PHP SAPI, Zend のバージョンを標準出力に出力します。例:

$ php -v
PHP 4.3.0 (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies

-w--strip

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

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

-z--zend-extension

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

 --ini

設定ファイルの名前、設定ファイルを検索するディレクトリを表示します。 PHP 5.2.3 以降で使用可能です。

例 43-3. --ini の例

$ php --ini
Configuration File (php.ini) Path: /usr/dev/php/5.2/lib
Loaded Configuration File:         /usr/dev/php/5.2/lib/php.ini
Scan for additional .ini files in: (none)
Additional .ini files parsed:      (none)

--rf--rfunction

指定した関数あるいはクラスメソッドについての情報 (たとえばパラメータの数と名前など) を表示します。 PHP 5.1.2 以降で使用可能です。

このオプションは、PHP が リフレクション のサポートつきでコンパイルされている場合にのみ使用可能です。

例 43-4. 基本的な --rf の使用法

$ php --rf var_dump
Function [ <internal> public function var_dump ] {

  - Parameters [2] {
    Parameter #0 [ <required> $var ]
    Parameter #1 [ <optional> $... ]
  }
}

--rc--rclass

指定したクラスについての情報 (定数、プロパティおよびメソッドの一覧) を表示します。PHP 5.1.2 以降で使用可能です。

このオプションは、PHP が リフレクション のサポートつきでコンパイルされている場合にのみ使用可能です。

例 43-5. --rc の例

$ php --rc Directory
Class [ <internal:standard> class Directory ] {

  - Constants [0] {
  }

  - Static properties [0] {
  }

  - Static methods [0] {
  }

  - Properties [0] {
  }

  - Methods [3] {
    Method [ <internal> public method close ] {
    }

    Method [ <internal> public method rewind ] {
    }

    Method [ <internal> public method read ] {
    }
  }
}

--re--rextension

指定した拡張モジュールについての情報 (php.ini オプション、 定義されている関数、定数およびクラスの一覧) を表示します。 PHP 5.1.2 以降で使用可能です。

このオプションは、PHP が リフレクション のサポートつきでコンパイルされている場合にのみ使用可能です。

例 43-6. --re の例

$ php --re json
Extension [ <persistent> extension #19 json version 1.2.1 ] {

  - Functions {
    Function [ <internal> function json_encode ] {
    }
    Function [ <internal> function json_decode ] {
    }
  }
}

--ri--rextinfo

指定した拡張モジュールについての設定情報 (phpinfo() が返す情報と同じもの) を表示します。 PHP 5.2.2 以降で使用可能です。コア機能に関する設定情報は、 "main" というモジュール名で取得できます。

例 43-7. --ri の例

$ php --ri date

date

date/time support => enabled
"Olson" Timezone Database Version => 2007.5
Timezone Database => internal
Default timezone => Europe/Oslo

Directive => Local Value => Master Value
date.timezone => Europe/Oslo => Europe/Oslo
date.default_latitude => 59.22482 => 59.22482
date.default_longitude => 11.018084 => 11.018084
date.sunset_zenith => 90.583333 => 90.583333
date.sunrise_zenith => 90.583333 => 90.583333

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

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

#!/usr/bin/php
<?php

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

これは、ひとつのオプションをとるコマンドラインの PHP スクリプトです。

  使用法:
  <?php echo $argv[0]; ?> <option>

  <option> は出力したい単語です。
  --help, -help, -h, あるいは -? を指定すると、
  このヘルプが表示されます。

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

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

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

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

例 43-9. コマンドライン 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 に関する ドキュメントも参照してください。