ビルトインウェブサーバー

警告

このウェブサーバーは、アプリケーション開発の支援用として設計されたものです。 テスト用に使ったり、制約のある環境でアプリケーションをデモするために使ったりすることもできるでしょう。 あらゆる機能を兼ね備えたウェブサーバーを目指したものではないので、 公開ネットワーク上で使ってはいけません。

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 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 を実行してください。 すべてのオプションがウェブサーバーの実行時に適用されるわけではありません。

警告

この機能は 実験的なもの であり、 本番環境で使うことを意図した機能では ありません。 ビルトインウェブサーバーは本番環境で使うものではありません。

例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

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

Windows 環境、かつ PHP 7.4.0 より前のバージョンでは、 ルーティングを行うスクリプトがシンボリックリンク先の静的なリソースを処理しない限り、 それらのリソースにアクセスできませんでした。

例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
警告

ビルトインウェブサーバーは、公開ネットワークで使うべきではありません。

+add a note

User Contributed Notes 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