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.