PHP built-in web server

PHP comes with a built-in web server for local development. The web server can be started and stopped via command line and has some basic configuration options.

Basic usage

After a successful installation of PHP the php command should be available on the terminal. This can be tested with a simple version check:

php --version

If PHP is installed correctly a version statement should be printed out on the terminal. For starting the built-in web server the -S command option can be used. The option require the address and port as arguments. E.g., on localhost port 8080 the web server can be started with the following command:

php -S localhost:8080

The -S option alone will take the current working directory as the webroot. This can be changed with the -t option. E.g., if /var/www/demo should be the webroot the command can be used as follows:

php -S localhost:8080 -t /var/www/demo

The PHP interpreter is configured with a global php.ini file, which holds all configuration options. For specifically overriding certain options for testing purposes or similar a php.ini file can be attached, which would override options from the global ini file. The example below would start the web server with a php.ini file from the current working directory.

php -S localhost:8080 -c php.ini

All files ending with a .php suffix will be processed as PHP code. The rest are served as files like on a normal web server. The built-in webserver can be stopped with the Ctrl-C shortcut.

Route file

Additionally, a route file can be attached to the web server. This can be used for url-rewriting or mocking certain requests. The route file is basically just a php script which either returns false if the request should be processed normally or otherwise provide an alternative response. The command for starting the web server with a route file looks like this:

php -S localhost:8080 -t /var/www/demo route.php

The command above would reference a route file named route.php inside the current working directoy. The following example of a route file would return a sample image (sample.png) for all image requests. All other requests are processed normally.

<?php

if ($_SERVER["REQUEST_URI"] != "/sample.png" &&
preg_match('/\.(?:png|jpeg|jpg|gif)$/', $_SERVER["REQUEST_URI"])) {
header("Location: /sample.png");
} else {
return false;
}

The route file can make the built-in web server act like a reverse proxy and internally request another resource e.g., from an external server. In the following example all requests to an API endpoint are rewritten to a different external API. The response is returned and for the client it looks like as if the request was handled by the built-in web server.

<?php

if (preg_match('/^\/api//', $_SERVER["REQUEST_URI"]) {
$external_uri = 'https://external-domain.com/restapi/' . substr($_SERVER["REQUEST_URI"], 5);
$method = $_SERVER['REQUEST_METHOD'];

$opts = [
"http" => [
"method" => $method,
"header" => "Content-type: application/json\r\n" ,
"content" => file_get_contents('php://input')
]
];

$context = stream_context_create($opts);
header('Content-type: application/json');
echo file_get_contents($uri, false, $context);
} else {
return false;
}

Logging

When the built-in web server is started a log output is attached to the standard output of the terminal. By using the error_log function with message type 4 log statements can be printed out there. E.g., a route file with the following contents would print all Cookie headers from the request. This can be a useful feature for monitoring and debugging an application in development.

<?php

error_log(print_r(getallheaders()['Cookie'], true), 4);
return false;

Conclusion

The built-in web server for PHP is a helpful tool for setting up a development environment quickly. It offers options like attaching a route file or printing log statements to the standard output, which are quite useful during development. Together with SQLite PHP can be effectively used as is for local development. Personally, I think instead of using things like XAMPP, MAMP or WampServer the built-in web server should be preferred.