为了设置项目特定的配置选项,只需将php.ini文件添加到您的项目中,然后使用此标志运行内置服务器
php -S localhost:8000 -c php.ini
这对于无法在运行时设置的设置(ini_set())尤其有用。
此Web服务器旨在辅助应用程序开发。它也可能用于测试目的或在受控环境中运行的应用程序演示。它并非旨在成为一个功能齐全的Web服务器。不应将其用于公共网络。
命令行接口(CLI) SAPI 提供了一个内置的Web服务器。
Web服务器仅运行一个单线程进程,因此如果请求被阻塞,PHP应用程序将停止响应。
URI请求来自启动PHP的当前工作目录,除非使用-t选项指定显式的文档根目录。如果URI请求未指定文件,则返回给定目录中的index.php或index.html。如果这两个文件都不存在,则会在父目录中继续查找index.php和index.html,直到找到一个文件或到达文档根目录为止。如果找到index.php或index.html,则返回该文件,并将$_SERVER['PATH_INFO']设置为URI的尾部部分。否则,返回404响应代码。
如果在启动Web服务器时命令行中给出了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开始,可以配置内置Web服务器以派生多个工作进程,以便测试需要对内置Web服务器进行多个并发请求的代码。在启动服务器之前,将PHP_CLI_SERVER_WORKERS环境变量设置为所需的工作进程数。
注意:此功能在Windows上不受支持。
此实验性功能不适用于生产环境。通常,内置Web服务器不适用于生产环境。
示例 #1 启动Web服务器
$ 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文件的请求将显示“欢迎使用PHP”
<?php
// router.php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
return false; // 按原样提供请求的资源。
} else {
echo "<p>欢迎使用PHP</p>";
}
?>
$ php -S localhost:8000 router.php
示例 #4 检查CLI Web服务器的使用
在使用CLI Web服务器进行开发以及稍后与生产Web服务器一起使用时,重用框架路由器脚本
<?php
// router.php
if (php_sapi_name() == 'cli-server') {
/* 路由静态资源并返回false */
}
/* 继续执行正常的index.php操作 */
?>
$ php -S localhost:8000 router.php
示例 #5 处理不受支持的文件类型
如果需要提供CLI Web服务器未处理其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 Web服务器
可以使用以下命令使Web服务器在8000端口上对任何接口都可访问
$ php -S 0.0.0.0:8000
不应在公共网络上使用内置Web服务器。
为了设置项目特定的配置选项,只需将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
4. 浏览器访问:
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包含点号,在使用内置Web服务器时,您将丢失`$_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", "\nRequested: $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"
)
) 这样,对于快速的Web测试,您只需将文件或文件夹“发送到”此bat文件,它就会打开您的浏览器并运行服务器。
要发送环境变量到PHP内置web服务器,请键入如下命令:
~$ MYENV=dev php -d variables_order=EGPCS -S 0.0.0.0:8000
在PHP脚本中,您可以使用以下代码进行检查:
<?php
echo getenv('MYENV'); // 输出 dev
我尝试使用内置web服务器,但在处理不包含点号和文件扩展名的静态文件时遇到了问题。
对于URI类似于“/testfile”的文件,web服务器返回200状态码,但没有任何内容。
我不确定这是否是bug,但我创建了一个router.php,它现在不再使用“return false;”操作来传递内置web服务器的静态文件。
我改用fpassthru()来处理。
此外,我的router.php可以配置为:
- ... 请求目录时使用特定的index文件
- ... 配置正则表达式路由,以便如果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;
}
}
// 如果请求的是目录,则检查index文件是否存在
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" does not exist', $_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;
内置Web服务器使用SAPI日志子系统。因此,所有消息都写入标准错误流,而不是标准输出流。
如果要将服务器日志保存到文件中,可以使用以下命令:
php -S 0.0.0.0:80 2>&1 | tee out.log