要設定專案特定的配置選項,只需將 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://:8000/ 和 https://: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://: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