Встроенный веб-сервер

Внимание

Веб-сервер предназначен для помощи в разработке приложений. Он также может быть полезным в тестовых целях или для демонстрации приложения, запускаемого в полностью контролируемом окружении. Он не выполняет функции полноценного веб-сервера и не должен использоваться в общедоступных сетях.

Модуль CLI SAPI содержит встроенный веб-сервер.

Веб-сервер выполняет только один однопоточный процесс, поэтому приложения PHP остановятся при блокировке запроса.

URI-запросы обслуживаются из текущей директории, в которой запустили PHP, если не указали опцию -t для переназначения корневого документа. При запросе URI, который не указывает на конкретный файл, возвращается файл index.php или index.html в заданной директории. При недоступности файлов поиск продолжается в родительских каталогах, пока веб-сервер не найдёт файл или не достигнет корня документа. При обнаружении файла index.html веб-сервер возвращает содержимое файла, а при обнаружении файла index.php — возвращается результат обработки. При этом в элемент $_SERVER['PATH_INFO'] записывается последняя часть URL-адреса, иначе в ответе возвращается 404-й код статуса.

Замечание:

Начиная с PHP 8.4.0 поиск индексного файла выполняется даже при запросе пути, который похож на путь к файлу — с точкой в последнем сегменте, по которому не получилось найти файл. Раньше такие запросы пропускали поиск и сразу возвращали в ответе 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 встроенный веб-сервер получил поддержку многопроцессного режима работы для тестирования кода, который требует нескольких одновременных запросов к встроенному веб-серверу. Перед запуском сервера для переменной среды PHP_CLI_SERVER_WORKERS устанавливают количество рабочих процессов, которое требуется для тестирования.

Замечание:

ОС Windows не поддерживает многопроцессный режим.

Замечание:

Информацию о параметрах, которые поддерживает PHP в режиме командной строки, возвращают команды php --help или man php. PHP проигнорирует параметры командной строки, которые не сочетаются с параметром запуска веб-сервера.

Внимание

Встроенный веб-сервер — экспериментальная функция, которая не рассчитана на работу в производственном окружении; сервер запускают только в целях разработки.

Пример #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

После URI-запросов http://localhost:8000/ и http://localhost:8000/myscript.html в консоли выведется примерно следующее:

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

Для совместного использования скрипта маршрутизации при разработке с веб-сервером CLI и в дальнейшем с рабочим (production) веб-сервером:

<?php

// router.php
if (php_sapi_name() == 'cli-server') {
    /* Маршрутизация статических ресурсов и возврат значения false */
}
/* Продолжение стандартных операций с файлом index.php */
$ php -S localhost:8000 router.php

Пример #5 Обработка неподдерживаемых типов файлов

Для обслуживания статического ресурса, MIME-тип которого не обрабатывается веб-сервером CLI, используйте это:

<?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
Внимание

Встроенный веб-сервер не должен использоваться в общедоступной сети.

+Добавить

Примечания пользователей 9 notes

up
125
jonathan at reinink dot ca
12 years ago
In order to set project specific configuration options, simply add a php.ini file to your project, and then run the built-in server with this flag:

php -S localhost:8000 -c php.ini

This is especially helpful for settings that cannot be set at runtime (ini_set()).
up
80
Mark Simon
10 years ago
It’s not mentioned directly, and may not be obvious, but you can also use this to create a virtual host. This, of course, requires the help of your hosts file.

Here are the steps:

1    /etc/hosts
    127.0.0.1    www.example.com

2    cd [root folder]
    php -S www.example.com:8000

3    Browser:
    http://www.example.com:8000/index.php

Combined with a simple SQLite database, you have a very handy testing environment.
up
53
oan at vizrt dot com
9 years ago
I painfully experienced behaviour that I can't seem to find documented here so I wanted to save everyone from repeating my mistake by giving the following heads up:

When starting php -S on a mac (in my case macOS Sierra) to host a local server, I had trouble with connecting from legacy Java. 

As it turned out, if you started the php server with 
"php -S localhost:80" 
the server will be started with ipv6 support only!

To access it via ipv4, you need to change the start up command like so:
 "php -S 127.0.0.1:80"
which starts server in ipv4 mode only.
up
31
tamas at bartatamas dot hu
12 years ago
If your URI contains a dot, you'll lose the $_SERVER['PATH_INFO'] variable, when using the built-in webserver.
I wanted to write an API, and use .json ending in the URI-s, but then the framework's routing mechanism broke, and it took a lot of time to discover that the reason behind it was its router relying on $_SERVER['PATH_INFO'].

References:
https://bugs.php.net/bug.php?id=61286
up
32
Ivan Ferrer
13 years ago
On Windows you may find useful to have a phpserver.bat file in shell:sendto with the folowing:
explorer http://localhost:8888
rem check if arg is file or dir
if exist "%~1\" (
  php -S localhost:8888 -t "%~1"
) else (
  php -S localhost:8888 -t "%~dp1"
)

then for fast web testing you only have to SendTo a file or folder to this bat and it will open your explorer and run the server.
up
27
matthes at leuffen dot de
10 years ago
To output debugging information on the command line you can write output to php://stdout:

<?php
$path = $_SERVER["SCRIPT_FILENAME"];

file_put_contents("php://stdout", "\nRequested: $path");
echo "<p>Hello World</p>";
?>
up
17
deep at deepshah dot me
6 years ago
Listen on all addresses of IPv4:
php -S 0.0.0.0:80

Listen on all addresses of IPv6:
php -S [::0]:80
up
-2
aroian at naiora dot fr
1 month ago
If you use a router script and a custom docroot the order of the parameters matters !

cd /path/to/project
php -S localhost:8000 router.php -t dist

In this case $_SERVER['DOCUMENT_ROOT'] is '/path/to/project'

While with

php -S localhost:8000 -t dist router.php

$_SERVER['DOCUMENT_ROOT'] is '/path/to/project/dist'

The argument parser seems to stop when it encounters router script positional argument.

This is especially important when you want to let the webserver handle files that exist by returning `false`.
up
0
sony at sony-ak dot com
6 years ago
To send environment variable as long as with PHP built-in web server, type like this.

~$ MYENV=dev php -d variables_order=EGPCS -S 0.0.0.0:8000

On PHP script we can check with this code.

<?php
  echo getenv('MYENV'); // print dev