從版本 4.3 開始,PHP 提供了一種新型別的 SAPI(Server Application Programming Interface,伺服端應用編程端口)支援,名為 CLI,意為 Command Line Interface,即命令行接口。顧名思義,該 SAPI 模塊主要用作 PHP 的開發外殼應用。CLI SAPI 和其它 SAPI 模塊相比有很多的不同之處,我們將在本章中詳細闡述。
CLI SAPI 最先是隨 PHP 4.2.0 版本發布的,但仍舊只是一個實驗性的版本,並需要在執行 ./configure 時加上 --enable-cli 參數。從 PHP 4.3.0 版本開始,CLI SAPI 成為了正式模塊,也因此將被永久地編譯並安裝為 PHP 二進制文件(即 Windows 下的 php.exe 文件)。
以下為 CLI SAPI 和其它 SAPI 模塊相比的顯著區別:
與 CGI SAPI 不同,其輸出沒有任何表頭訊息。
儘管 CGI SAPI 提供了取消 HTTP 表頭訊息的方法,但在 CLI SAPI 中並不存在類似的方法以開啟 HTTP 表頭訊息的輸出。
CLI 預定以安靜模式開始,但為了保証相容性, -q 參數使得您可以使用舊的 CGI 腳本。
在執行時,不會把工作目錄改為腳本的當前目錄。(您可以使用 -C 參數來相容 CGI 模式)。
出錯時輸出純文字的錯誤訊息(非 HTML 格式)。
CLI SAPI 強制更改了 php.ini 中的某些設置,因為這些設置在外殼環境下是沒有意義的。
表格 23-1. 被更改的 php.ini 設置選項
| 設置選項 | CLI SAPI 預設值 | 備注 |
|---|---|---|
| html_errors | FALSE | 無意義的 HTML 標記符會使得出錯訊息很凌亂,所以在外殼下閱讀報錯訊息是十分困難的。因此將該選項的預設值改為 FALSE。 |
| implicit_flush | TRUE | 在命令行模式下,所有來自 print() 和 echo() 的輸出將被立即寫到輸出端,而不作任何地緩衝操作。如果您希望延緩或控制標準輸出,您仍然可以使用 output buffering 設置項。 |
| max_execution_time | 0 (無限值) | 鑒於在外殼環境下使用 PHP 的無窮的可能性,最大執行時間被設置為了無限值。為 WEB 開發的應用程序可能只需執行幾秒鐘時間,而外殼應用程序的執行時間可能會長的多。 |
| register_argc_argv | TRUE | 在使用 CLI SAPI 時,PHP 的全域變數 $argc(傳送給應用程序的參數的個數)及 $argv(實際參數的陣列)將總是有效並被賦於對應的值。 |
註: 這些設置無法在設置文件 php.ini 或任何指定的其它文件中被初始化為其它值。這些預設值被限制在所有其它的設置文件被解析後改變。不過,它們的值可以在程序執行的過程中被改變(儘管對於該執行過程來說,這些設置項是沒有意義的)。
為了減輕外殼環境下的工作,我們定義了如下常數:
表格 23-2. CLI 專用常數
| 常數名稱 | 描 述 | |
|---|---|---|
| STDIN |
一個已打開的指向 stdin 的流。您可以用如下方法來呼叫:
| |
| STDOUT |
一個已打開的指向 stdout 的流。您可以用如下方式來呼叫:
| |
| STDERR |
一個已打開的指向 stdout 的流。您可以用如下方式來呼叫:
|
有了以上常數,您就無需自己建立指向諸如 stderr 的流,只需簡單的使用這些常數來代替流指向:
php -r 'fwrite(STDERR, "stderr\n");' |
CLI SAPI 不會將當前目錄改為已執行的腳本所在的目錄。
以下範例顯示了本模塊與 CGI SAPI 模塊之間的不同:
<?php
/* Our simple test application */
echo getcwd(), "\n";
?> |
在使用 CGI 版本時,其輸出為
$ pwd /tmp $ php-cgi -f another_directory/test.php /tmp/another_directory |
我們明顯可以看到 PHP 將當前目錄改成了剛剛執行過的腳本所在的目錄。
使用 CLI SAPI 模式,我們得到:
$ pwd /tmp $ php -f another_directory/test.php /tmp |
註: 您可以在命令行執行時給 CGI SAPI 加上 -C 參數,使其支援 CLI SAPI 的功能。
以下是 PHP 二進制文件(即 php.exe 程序)提供的命令行模式的選項參數,您隨時可以通過 PHP -h 命令來查詢這些參數。
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 代碼:
讓 PHP 執行指定文件。
php my_script.php php -f my_script.php |
以上兩種方法(使用或不使用 -f 參數)都能夠執行給定的 my_script.php 文件。您可以選擇任何文件來執行,您指定的 PHP 腳本並非必須要以 .php 為擴展名,它們可以有任意的文件名和擴展名。
在命令行直接執行 PHP 代碼。
php -r 'print_r(get_defined_constants());' |
在使用這種方法時,請您注意外殼變數的替代及引號的使用。
註: 請仔細閱讀以上範例,在執行代碼時沒有開始和結束的標記符!加上 -r 參數後,這些標記符是不需要的,加上它們會導致語法錯誤。
通過標準輸入(stdin)提供需要執行的 PHP 代碼。
以上用法給我們提供了非常強大的功能,使得我們可以如下範例所示,動態地產生 PHP 代碼並通過命令行執行這些代碼:
$ some_application | some_filter | php | sort -u >final_output.txt |
以上三種執行代碼的方法不能同時使用。
和所有的外殼應用程序一樣,PHP 的二進制文件(php.exe 文件)及其執行的 PHP 腳本能夠接受一系列的參數。PHP 沒有限制傳送給腳本程序的參數的個數(外殼程序對命令行的字元數有限制,但您通常都不會超過該限制)。傳遞給您腳本的參數可在全域變數 $argv 中獲取。該陣列中下標為零的成員為腳本的名稱(當 PHP 代碼來自標準輸入獲直接用 -r 參數以命令行方式執行時,該名稱為“-”)。另外,全域變數 $argc 存有 $argv 陣列中成員變數的個數(而非傳送給腳本程序的參數的個數)。
只要您傳送給您腳本的參數不是以 - 符號開頭,您就無需過多的注意什麼。向您的腳本傳送以 - 開頭的參數會導致錯誤,因為 PHP 會認為應該由它自身來處理這些參數。您可以用參數列表分隔符 -- 來解決這個問題。在 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 代碼,然後為該文件設置正確的執行屬性。該方法可以使得該文件能夠像外殼腳本或 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 標記符塊,並不包含任何的 HTML 頭。
| |||
| -w |
顯示除去了註釋和空格的原始碼。
| |||
| -f |
解析並執行給定的文件名。該參數為可選參數且可以不加,僅指明需要執行的文件名即可。 | |||
| -v |
將 PHP、PHP SAPI 及 Zend 的版本訊息寫入的標準輸出。例如:
| |||
| -c |
用該參數,您可以指定一個放置 php.ini 文件的目錄,或者直接指定一個自定義的 INI 文件,其文件名可以不是 php.ini。例如:
| |||
| -a |
交互地執行 PHP。 | |||
| -d |
用該參數可以自行設置 php.ini 文件中設置變數的值,其語法為:
範例:
| |||
| -e |
為調試器等產生擴展訊息。 | |||
| -z |
加載 Zend 擴展庫。如果僅給定一個文件名,PHP 將試圖從您系統擴展庫的預定路徑(在 Linux 系統下,該路徑通常由 /etc/ld.so.conf 指定)加載該擴展庫。如果您用一個絕對路徑指定文件名,則系統的擴展庫預定路徑將不會被使用。如果用相對路徑指定的文件名,PHP 則僅試圖加載相對於當前目錄的擴展庫。 | |||
| -l |
該參數提供了對指定 PHP 代碼進行語法檢查的方便的方法。如果成功,則向標準輸出寫入 No syntax errors detected in <filename> 字串,並且外殼傳回值為 0。如果失敗,則 Errors parsing <filename> 以及內部解析器錯誤訊息會一起被寫入到標準輸出,同時外殼傳回值將別設置為 255。 該參數將無法檢查致命錯誤(如未定義函式),如果您希望檢測之名錯誤,請使用 -f 參數。
| |||
| -m |
使用該參數,PHP 將顯示出內置以及已加載的 PHP 及 Zend 模塊:
| |||
| -i | 該命令行參數會呼叫 phpinfo() 函式,並顯示出結果。如果 PHP 沒有正常工作,我們建議您執行 php -i 命令來查看在訊息表格之前或者對應的地方是否有任何錯誤訊息輸出。請注意輸出的內容為 HTML 格式,因此輸出的訊息篇幅較大。 | |||
| -r |
使用該參數可以在命令行執行 PHP 代碼。您無需加上 PHP 的起始和結束標籤(<?php 和 ?>),否則將會導致語法解析錯誤。
| |||
| -h | 使用該參數,您可以得到完整的命令行參數的列表及這些參數作用的簡單描述。 |
PHP 的命令行模式能使得 PHP 腳本能完全獨立於 WEB 伺服器單獨執行。如果您使用 Unix 系統,您需要在您的 PHP 腳本的最前面加上一行特殊的代碼,使得它能夠被執行,這樣系統就能知道用什麼樣的程序要執行該腳本。在 Windows 平台下您可以將 php.exe 和 .php 文件的雙擊屬性相關聯,您也可以編寫一個批處理文件來用 PHP 執行腳本。為 Unix 系統增加的第一行代碼不會影響該腳本在 Windows 下的執行,因此您也可以用該方法編寫跨平台的腳本程序。以下是一個簡單的PHP 命令行程序的範例。
在以上腳本中,我們用第一行特殊的代碼來指明該文件應該由 PHP 來執行。我們在這裡使用 CLI 的版本,因此不會有 HTTP 表頭訊息輸出。在您用 PHP 編寫命令行應用程序時,您可以使用兩個參數:$argc 和 $argv。前面一個的值是比參數個數大 1 的整數(執行的腳本本身的名稱也被當作一個參數)。第二個時包含有參數的陣列,其第一個元素為腳本的名稱,下標為數字 0($argv[0])。
在以上程序中我們檢查了參數的個數是大於 1 個還是小於 1 個。即時參數是 --help、-help、-h 或 -?,我們仍然顯示出幫助訊息,並同時動態輸出腳本的名稱。如果還收到了其它參數,我們也把它們顯示出來。
如果您希望在 Unix 下執行以上腳本,您需要使得它成為可執行腳本,然後簡單的執行 script.php echothis 或 script.php -h。在 Windows 下,您可以為此編寫一個批處理文件:
假設您將上述程序命名為 script.php,且您的 php.exe 文件放置在 c:\php\php.exe,該批處理文件會幫助您將附加的參數傳給腳本程序: script.bat echothis 或 script.bat -h。
請參閱 Readline 擴展模塊的有關文檔,以獲取更多的函式的訊息。這些函式可以幫助您完善您的 PHP 命令行應用程序。