要設定專案特定的配置選項,只需將 php.ini 檔案新增到您的專案中,然後使用以下旗標執行內建伺服器
php -S localhost:8000 -c php.ini
這對於無法在執行期間設定 (ini_set()) 的設定特別有用。
此網路伺服器旨在輔助應用程式開發。它也可能適用於測試目的或在受控環境中執行的應用程式示範。它並非設計用於功能齊全的網路伺服器。不應在公共網路上使用。
CLI SAPI 提供內建的網路伺服器。
網路伺服器僅執行單一執行緒的行程,因此如果請求被封鎖,PHP 應用程式將會停滯。
URI 請求會從 PHP 啟動時的目前工作目錄提供服務,除非使用 -t 選項指定明確的 文件根目錄。如果 URI 請求未指定檔案,則會傳回指定目錄中的 index.php 或 index.html。如果兩個檔案都不存在,則會在父目錄中繼續搜尋 index.php 和 index.html,依此類推,直到找到其中一個或到達文件根目錄為止。如果找到 index.php 或 index.html,則會傳回該檔案,並將 $_SERVER['PATH_INFO'] 設定為 URI 的尾端部分。否則會傳回 404 回應碼。
如果在啟動網頁伺服器時在命令列上指定了 PHP 檔案,則該檔案會被視為「路由器」腳本。此腳本會在每個 HTTP 請求開始時執行。如果此腳本傳回 **false
**,則會按原樣傳回所請求的資源。否則,腳本的輸出會傳回瀏覽器。
具有以下副檔名的檔案會傳回標準 MIME 類型:.3gp
、.apk
、.avi
、.bmp
、.css
、.csv
、.doc
、.docx
、.flac
、.gif
、.gz
、.gzip
、.htm
、.html
、.ics
、.jpe
、.jpeg
、.jpg
、.js
、.kml
、.kmz
、.m4a
、.mov
、.mp3
、.mp4
、.mpeg
、.mpg
、.odp
、.ods
、.odt
、.oga
、.ogg
、.ogv
、.pdf
、.png
、.pps
、.pptx
、.qt
、.svg
、.swf
、.tar
、.text
、.tif
、.txt
、.wav
、.webm
、.wmv
、.xls
、.xlsx
、.xml
、.xsl
、.xsd
、.zip
。
從 PHP 7.4.0 開始,內建網頁伺服器可以設定為 fork 多個 worker,以便測試需要多個併發請求到內建網頁伺服器的程式碼。在啟動伺服器之前,將 PHP_CLI_SERVER_WORKERS 環境變數設定為所需的 worker 數量。
注意:Windows 不支援此功能。
此*實驗性*功能*不*適用於生產環境。一般來說,內建網頁伺服器*不*適用於生產環境。
範例 #1 啟動網頁伺服器
$ cd ~/public_html $ php -S localhost:8000
終端機將顯示
PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011 Listening on localhost:8000 Document root is /home/me/public_html Press Ctrl-C to quit
在對 https://127.0.0.1:8000/ 和 https://127.0.0.1:8000/myscript.html 發出 URI 請求後,終端機將顯示類似以下內容:
PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011 Listening on localhost:8000 Document root is /home/me/public_html Press Ctrl-C to quit. [Thu Jul 21 10:48:48 2011] ::1:39144 GET /favicon.ico - Request read [Thu Jul 21 10:48:50 2011] ::1:39146 GET / - Request read [Thu Jul 21 10:48:50 2011] ::1:39147 GET /favicon.ico - Request read [Thu Jul 21 10:48:52 2011] ::1:39148 GET /myscript.html - Request read [Thu Jul 21 10:48:52 2011] ::1:39149 GET /favicon.ico - Request read
請注意,在 PHP 7.4.0 之前,除非路由器腳本處理這些符號連結的靜態資源,否則在 Windows 上無法存取它們。
範例 #2 使用特定文件根目錄啟動
$ cd ~/public_html $ php -S localhost:8000 -t foo/
終端機將顯示
PHP 5.4.0 Development Server started at Thu Jul 21 10:50:26 2011 Listening on localhost:8000 Document root is /home/me/public_html/foo Press Ctrl-C to quit
範例 #3 使用路由器腳本
在此範例中,對圖片的請求將顯示圖片,但對 HTML 檔案的請求將顯示「Welcome to PHP」。
<?php
// router.php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
return false; // 直接提供請求的資源。
} else {
echo "<p>Welcome to PHP</p>";
}
?>
$ php -S localhost:8000 router.php
範例 #4 檢查 CLI 網頁伺服器的使用
在開發過程中使用 CLI 網頁伺服器,以及稍後在正式網頁伺服器上重複使用框架路由器腳本
<?php
// router.php
if (php_sapi_name() == 'cli-server') {
/* 路由靜態資源並返回 false */
}
/* 繼續執行一般的 index.php 操作 */
?>
$ php -S localhost:8000 router.php
範例 #5 處理不支援的檔案類型
如果您需要提供 CLI 網頁伺服器未處理的 MIME 類型的靜態資源,請使用
<?php
// router.php
$path = pathinfo($_SERVER["SCRIPT_FILENAME"]);
if ($path["extension"] == "el") {
header("Content-Type: text/x-script.elisp");
readfile($_SERVER["SCRIPT_FILENAME"]);
}
else {
return FALSE;
}
?>
$ php -S localhost:8000 router.php
範例 #6 從遠端機器存取 CLI 網頁伺服器
您可以使用以下指令,讓任何介面都能透過 8000 連接埠存取網頁伺服器
$ php -S 0.0.0.0:8000
內建網頁伺服器不應在公開網路上使用。
要設定專案特定的配置選項,只需將 php.ini 檔案新增到您的專案中,然後使用以下旗標執行內建伺服器
php -S localhost:8000 -c php.ini
這對於無法在執行期間設定 (ini_set()) 的設定特別有用。
這並沒有直接提及,而且可能不太明顯,但您也可以使用它來建立虛擬主機。當然,這需要 hosts 檔案的協助。
步驟如下
1 /etc/hosts
127.0.0.1 www.example.com
2. 切換目錄至網站根目錄
php -S www.example.com:8000
3. 開啟瀏覽器
http://www.example.com:8000/index.php
搭配一個簡單的 SQLite 資料庫,您就有一個非常方便的測試環境。
我痛苦地經歷了一個似乎沒有在此記錄的行為,因此我想透過以下提醒來避免大家重蹈覆轍。
在 Mac(我的例子是 macOS Sierra)上啟動 php -S 來架設本地伺服器時,我遇到了從舊版 Java 連線的問題。
結果發現,如果您使用以下指令啟動 PHP 伺服器:
"php -S localhost:80"
伺服器將僅以 IPv6 支援啟動!
要透過 IPv4 存取它,您需要像這樣更改啟動指令:
"php -S 127.0.0.1:80"
這會僅以 IPv4 模式啟動伺服器。
如果您的 URI 包含點號,則在使用內建網路伺服器時,您將遺失 $_SERVER['PATH_INFO'] 變數。
我想要編寫一個 API,並在 URI 中使用 .json 結尾,但後來框架的路由機制失效了,我花了很多時間才發現其背後的原因是它的路由器依賴於 $_SERVER['PATH_INFO']。
參考資料
https://bugs.php.net/bug.php?id=61286
要在命令列上輸出除錯資訊,您可以將輸出寫入 php://stdout
<?php
$path = $_SERVER["SCRIPT_FILENAME"];
file_put_contents("php://stdout", "\n請求: $path");
echo "<p>Hello World</p>";
?>
在 Windows 上,您可能會發現將 phpserver.bat 檔案放在 shell:sendto 中很有用,內容如下:
explorer https://127.0.0.1:8888
rem 檢查參數是檔案還是目錄
if exist "%~1\" (
php -S localhost:8888 -t "%~1"
) else (
php -S localhost:8888 -t "%~dp1"
)
然後,為了快速進行網頁測試,您只需將檔案或資料夾「傳送到」這個 bat 檔案,它就會開啟您的檔案總管並執行伺服器。
要使用 PHP 內建網路伺服器傳送環境變數,請輸入如下內容:
~$ MYENV=dev php -d variables_order=EGPCS -S 0.0.0.0:8000
在 PHP 腳本中,我們可以使用以下程式碼進行檢查。
<?php
echo getenv('MYENV'); // 顯示 dev
我試著用內建的網頁伺服器,但在處理沒有附檔名(沒有點號和副檔名)的靜態檔案時遇到了一些問題。
對於像 "/testfile" 這樣的 URI,網頁伺服器會回應 200 卻沒有任何內容。
我不確定這是不是一個 bug,但我建立了一個 router.php,它不再使用 "return false;" 操作來讓內建網頁伺服器處理靜態檔案。
我改用 fpassthru() 來處理。
除此之外,我的 router.php 還可以設定成...
- ... 在請求目錄時,指定特定的索引檔案
- ... 設定正規表達式路由,以便在 REQUEST_URI 符合正規表達式時,請求特定的檔案或目錄。(類似您在 nginx 設定檔或 .htaccess 的 ModRewrite 中會做的事情)
也許有人會覺得這很有幫助。
================================
<?php
$indexFiles = ['index.html', 'index.php'];
$routes = [
'^/api(/.*)?$' => '/index.php'
];
$requestedAbsoluteFile = dirname(__FILE__) . $_SERVER['REQUEST_URI'];
// 檢查請求是否符合已定義的路由
foreach ($routes as $regex => $fn)
{
if (preg_match('%'.$regex.'%', $_SERVER['REQUEST_URI']))
{
$requestedAbsoluteFile = dirname(__FILE__) . $fn;
break;
}
}
// 如果請求是一個目錄,則檢查索引檔案是否存在
if (is_dir($requestedAbsoluteFile))
{
foreach ($indexFiles as $filename)
{
$fn = $requestedAbsoluteFile.'/'.$filename;
if (is_file($fn))
{
$requestedAbsoluteFile = $fn;
break;
}
}
}
// 如果請求的檔案不存在或是一個目錄 => 404
if (!is_file($requestedAbsoluteFile))
{
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
printf('"%s" 不存在', $_SERVER['REQUEST_URI']);
return true;
}
// 如果請求的檔案不是 php 檔案
if (!preg_match('/\.php$/', $requestedAbsoluteFile)) {
header('Content-Type: '.mime_content_type($requestedAbsoluteFile));
$fh = fopen($requestedAbsoluteFile, 'r');
fpassthru($fh);
fclose($fh);
return true;
}
// 如果請求的檔案是 php 檔案,則引入它
include_once $requestedAbsoluteFile;
內建網路伺服器使用 SAPI 記錄子系統。因此,所有訊息都會寫入標準錯誤,而不是標準輸出串流。
如果您想將伺服器日誌儲存到檔案中,可以使用以下指令:
php -S 0.0.0.0:80 2>&1 | tee out.log