2024 年日本 PHP 研討會

執行 PHP 檔案

有三種不同的方法可以將 PHP 程式碼提供給 CLI SAPI 執行

  1. 指示 PHP 執行特定檔案。

    $ php my_script.php
    
    $ php -f my_script.php
    

    兩種方法(無論是否使用 -f 參數)都會執行檔案 my_script.php。請注意,對於可以執行的檔案沒有限制;特別是,檔名不需要具有 .php 副檔名。

  2. 直接在命令列上传递要執行的 PHP 程式碼。

    $ php -r 'print_r(get_defined_constants());'
    

    對於 shell 變數替換和引號的使用,必須特別小心。

    注意事項:

    仔細閱讀範例:沒有起始或結束標籤! -r 參數根本不需要它們,使用它們將導致解析錯誤。

  3. 透過標準輸入 (stdin) 提供要執行的 PHP 程式碼。

    這提供了動態創建 PHP 程式碼並將其饋送到二進位檔的強大功能,如下列(虛構)範例所示

    $ some_application | some_filter | php | sort -u > final_output.txt
    
您無法合併三種執行程式碼的方式。

與每個 shell 應用程式一樣,PHP 二進位檔接受許多參數;然而,PHP 腳本也可以接收更多參數。傳遞給腳本的參數數量不受 PHP 限制(雖然 shell 對可傳遞的字元數有限制,但通常不太可能達到此限制)。傳遞給腳本的參數可在全域陣列 $argv 中取得。第一個索引(零)永遠包含從命令列呼叫的腳本名稱。請注意,如果使用命令列參數 -r 執行程式碼,$argv[0] 的值將會是 "Standard input code";在 PHP 7.2.0 之前,它是一個破折號 ("-")。如果程式碼是透過 STDIN 的管道執行,情況也是如此。

第二個全域變數 $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 the script and prevent PHP from showing its usage
$ php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}

然而,在 Unix 系統上,還有另一種使用 PHP 撰寫 shell 腳本的方法:讓腳本的第一行以 #!/usr/bin/php 開頭(如果您的 PHP CLI 二進位檔的路徑不同,則使用該路徑)。檔案的其餘部分應包含一般 PHP 程式碼,並使用常用的 PHP 起始和結束標籤。一旦檔案的執行屬性設定正確(例如 chmod +x test),就可以像執行任何其他 shell 或 perl 腳本一樣執行該腳本。

範例 #1 將 PHP 腳本作為 shell 腳本執行

#!/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 可執行檔可用於完全獨立於網路伺服器執行 PHP 腳本。在 Unix 系統上,應在 PHP 腳本中加入特殊的 #!(或稱「shebang」)第一行,以便系統可以自動判斷應該執行腳本的程式。在 Windows 平台上,可以將 php.exe.php 副檔名的雙擊選項關聯,或者可以建立批次檔來透過 PHP 執行腳本。Unix 的特殊 shebang 第一行程式碼在 Windows 上沒有影響(因為它的格式是 PHP 註解),因此可以透過包含它來撰寫跨平台程式。下面顯示了一個撰寫命令列 PHP 程式的簡單範例。

範例 #2 從命令列執行的指令碼 (script.php)

#!/usr/bin/php
<?php

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

這是一個帶有一個選項的命令列 PHP 指令碼。

用法
<?php echo $argv[0]; ?> <選項>

<選項> 可以是您想要輸出的任何文字。 使用 --help、-help、-h
或 -? 選項,您可以獲得此說明。


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

上面的指令碼在第一行包含了 Unix shebang,表示此檔案應該由 PHP 執行。 我們這裡使用的是CLI 版本,因此不會輸出 HTTP 標頭。

程式首先檢查是否存在所需的單一參數(除了指令碼名稱,它也被計算在內)。 如果沒有,或者參數是 --help-help-h-?,則會印出說明訊息,使用 $argv[0] 動態印出在命令列中輸入的指令碼名稱。 否則,參數將會原樣輸出。

要在 Unix 上執行上述指令碼,必須使其可執行,並簡單地呼叫為 script.php echothisscript.php -h。 在 Windows 上,可以建立類似以下的批次檔來執行此任務

範例 #3 用於執行命令列 PHP 指令碼的批次檔 (script.bat)

@echo OFF
"C:\php\php.exe" script.php %*

假設上述程式命名為 script.php,且 CLI php.exe 位於 C:\php\php.exe,則此批次檔將執行它,並傳遞所有附加的選項:script.bat echothisscript.bat -h

另請參閱 Readline 擴充套件文件,以了解更多可用於增強 PHP 命令列應用程式的函式。

在 Windows 上,可以將 PHP 設定為無需提供 C:\php\php.exe.php 副檔名即可執行,如 Microsoft Windows 上的命令列 PHP 中所述。

注意事項:

在 Windows 上,建議在實際的使用者帳戶下執行 PHP。 在網路服務下執行時,某些操作將會失敗,因為「未完成帳戶名稱和安全識別碼之間的對應」。

新增註釋

使用者貢獻的註釋 5 則註釋

php at richardneill dot org
11 年前
在 Linux 上,shebang (#!) 行會被核心最多解析成兩個部分。
例如:

1: #!/usr/bin/php
2: #!/usr/bin/env php
3: #!/usr/bin/php -n
4: #!/usr/bin/php -ddisplay_errors=E_ALL
5: #!/usr/bin/php -n -ddisplay_errors=E_ALL

1. 是啟動腳本的標準方式。(參考 "#!/bin/bash"。)

2. 使用 "env" 來查找 PHP 的安裝位置:它可能位於 $PATH 中的其他位置,例如 /usr/local/bin。

3. 如果您不需要使用 env,您可以在這裡傳遞一個參數。例如,要忽略系統的 PHP.ini 並使用預設值,請使用 "-n"。(參見 "man php"。)

4. 或者,您可以設定一個設定變數。我推薦這個,因為如果在這裡設定 display_errors,它會實際生效。否則,您唯一可以啟用它的位置是在 php.ini 中進行全系統設定。如果您嘗試在腳本本身中使用 ini_set(),那就太晚了:如果您的腳本有語法錯誤,它會無聲無息地停止執行。

5. 在 Linux 上(截至 2013 年)這將不起作用。它的行為就像整個字串 "-n -ddisplay_errors=E_ALL" 是一個單一參數一樣。但在 BSD 中,shebang 行可以接受兩個以上的參數,因此它可能會按預期工作。

總結:使用 (2) 獲得最大的可攜性,使用 (4) 獲得最大的除錯能力。
email at alexander-bombis dot de
3 年前
對於 Windows:

經過這些年,我還發現了一個事實,就是在 Windows shell 上,我必須在 php -r 後面使用雙引號。

但在 PowerShell 中,您可以使用單引號或雙引號!
gabriel at figdice dot org
8 年前
關於 shebang:

在 Linux 和 Windows 中,當您在 CLI 中使用以下指令執行腳本時:

php script.php

如果您的腳本的第一行以 `#!` 開頭,那麼 PHP 將會忽略它。

#!

所以,當腳本文件可執行時,這一行不僅會被核心吸收,還會被 PHP 引擎本身忽略。

但是,引擎不會忽略「外部」script.php 中任何包含文件的第一個 #! 行。
包含腳本中的任何「shebang」行都只會將該行輸出到 STDOUT,就像位於 <?php ... ?> 區塊之外的任何其他文字一樣。
david at frankieandshadow dot com
8 年前
如上所述,在文件開頭使用 #!/usr/bin/php 時的一個陷阱:

如果您最初在 Windows 上編輯文件,然後嘗試在 Unix 上使用它,它將無法正常工作,因為 #! 行需要 Unix 行尾。如果它具有 DOS 行尾,Bash 會顯示以下錯誤訊息:
「bash: /usr/local/bin/wpreplace.php: /usr/bin/php^M: bad interpreter: No such file or directory」

(在 Emacs 中,我使用「CTRL-X ENTER f」,然後輸入「unix」並按下 ENTER 鍵進行轉換)
spencer at aninternetpresence dot net
13 年前
如果您在 Windows 上運行 CLI 並使用「-r」選項,請務必將您的 PHP 程式碼用雙引號(而不是單引號)括起來。否則,您的程式碼將無法運行。
To Top