Running PHP 5.4 built-in web server outside localhost
I did these tests on a Windows XP system, but should work the same on Linux as well by modifying the commands.
Run your PHP test server like this:
C:/php/php.exe -S 0.0.0.0:80
or
/usr/bin/php -S 0.0.0.0:80
0.0.0.0 will bind to all available IP addresses on the system.On another machine on the network, I configured the hosts file to point to the internal IP of the system running PHP using a custom domain. This is not 127.0.0.1 as that refers to the local host, in my case I pointed my main PC to 192.168.88.247 which was the XP machine running PHP. Note the firewall should be disabled or set to allow traffic on port 80 on the machine running php.
I configured my router to port forward traffic from external port 80 to 192.168.88.247:80. Then using a hosts file on a PC from an external network, I configured the fake domain to point to my WAN IP. I was able to access the PHP web server externally.
That said, it is just a server for testing, so there may be unknown security risks opening it up to the outside world.
PHP 5.4 Built-in web server on home network
According to this answer you should be able to make PHP listen on all interfaces using a command-line parameter :
For Windows :
C:/php/php.exe -S 0.0.0.0:80
or, for GNU/Linux :/usr/bin/php -S 0.0.0.0:80
Routing PHP 5.4+ Built-in Web Server like .htaccess
<?php
$_matches = array();
/**
* Initialize the rewrite environment.
*/
function initialize() {
set_environment($_SERVER['REQUEST_URI']);
}
/**
* Set important environment variables and re-parse the query string.
* @return boolean
*/
function finalize() {
if (defined('REWRITER_FINALIZED')) return false;
define('REWRITER_FINALIZED', true);
if (\is_file($_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_NAME'])) {
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_NAME'];
}
if (isset($_SERVER['QUERY_STRING'])) {
$_GET = [];
parse_str($_SERVER['QUERY_STRING'], $_GET);
}
$_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'];
return true;
}
/**
* Adjust the server environment variables to match a given URL.
* @param string $url
*/
function set_environment($url) {
$url = rtrim($url, '&?');
$request_uri = $script_name = $url;
$query_string = null;
if (strpos($url, '?') > 0) {
$script_name = substr($url, 0, strpos($url, '?'));
$query_string = substr($url, 1 + strpos($url, '?'));
}
$_SERVER['REQUEST_URI'] = $request_uri;
$_SERVER['SCRIPT_NAME'] = $script_name;
$_SERVER['QUERY_STRING'] = $query_string;
}
/**
* Parse regular expression matches. eg. $0 or $1
* @param string $url
* @return string
*/
function parse_matches($url) {
$replace = function($bit) {
global $matches;
return isset($matches[$bit[1]])
? $matches[$bit[1]]
: null;
};
return preg_replace_callback('/\$([0-9]+)/', $replace, $url);
}
/**
* Parse Apache style rewrite parameters. eg. %{QUERY_STRING}
* @param string $url
* @return string
*/
function parse_parameters($url) {
$replace = function($bit) {
return isset($_SERVER[$bit[1]])
? $_SERVER[$bit[1]]
: null;
};
return preg_replace_callback('/%\{([A-Z_+]+)\}/', $replace, $url);
}
/**
* Change the internal url to a different url.
* @param string $from Regular expression to match current url, or optional when used in conjunction with `test`.
* @param string $to URL to redirect to.
* @return boolean
*/
function rewrite($from, $to = null) {
if (defined('REWRITER_FINALIZED')) return false;
$url = $_SERVER['SCRIPT_NAME'];
if (isset($to)) {
$url = preg_replace($from, $to, $url);
} else {
$url = parse_matches($from);
}
set_environment(
parse_parameters($url)
);
return true;
}
/**
* Compare a regular expression against the current request, store the matches for later use.
* @return boolean
*/
function test($expression) {
global $matches;
if (defined('REWRITER_FINALIZED')) return false;
return 0 < (integer)preg_match($expression, $_SERVER['SCRIPT_NAME'], $matches);
}
initialize();
// Your rewrite rules here.
test('%/(.*)-(.*)\.htm$%') && rewrite('/?page=$1&sub=$2&%{QUERY_STRING}') && finalize();
test('%^([^/]*)\.htm$%') && rewrite('/?page=$0&%{QUERY_STRING}') && finalize();
echo "<pre>";
var_dump($_SERVER);
// include index.php or something
I've included a bunch of 'helper' functions which will make it easier to write your rewrite rules (borrowed here). I cannot reach php built-in server running on a VM
You are binding your server to localhost
. It is only listening on the localhost
network interface. It won't be accessible outside of that machine.
Tell it to listen on your externally facing IP address instead.
Alternatively, tell it to listen on all network interfaces:
php -S 0.0.0.0:9889
Why PHP built-in web server should not be used on a public network?
From the documentation:
Also, it won't restart by itself if for a reason or another the process crashes.The web server runs only one single-threaded process, so PHP
applications will stall if a request is blocked.
In a pinch, it's a good tool, but it's definitely not be used on a public network.
Fatfree routing with PHP built-in web server
Your issue is directly related to the way you're using the PHP built-in web server.
As stated in the PHP docs, here's how the server handles requests:
URI requests are served from the current working directory where PHP was started, unless the -t option is used to specify an explicit document root. If a URI request does not specify a file, then either index.php or index.html in the given directory are returned. If neither file exists, the lookup for index.php and index.html will be continued in the parent directory and so on until one is found or the document root has been reached. If an index.php or index.html is found, it is returned and $_SERVER['PATH_INFO'] is set to the trailing part of the URI. Otherwise a 404 response code is returned.That means that, by default (without a router script), the web server is doing a pretty good job for routing unexisting URIs to your document rootIf a PHP file is given on the command line when the web server is started it is treated as a "router" script. The script is run at the start of each HTTP request. If this script returns FALSE, then the requested resource is returned as-is. Otherwise the script's output is returned to the browser.
index.php
file.In other words, provided your file structure is like:
lib/
base.php
template.php
etc.
public/
index.php
The following command is enough to start your server and dispatch the requests properly to the framework:php -S 0.0.0.0:8090 -t public/
Or if you're running the command directly from the public/ folder:cd public
php -S 0.0.0.0:8090
Beware that the working directory of your application depends on the folder from which you call the command. In order to leverage this value, I strongly advise you to add chdir(__DIR__);
at the top of your public/index.php
file. This way, all subsequent require
calls will be relative to your public/
folder. For ex: $f3 = require('../lib/base.php');
Routing file-style URIs
The built-in server, by default, won't pass unexisting file URIs to yourindex.php
, as stated in:If a URI request does not specify a file, then either index.php or index.html in the given directory are returnedSo if you plan to define some routes with dots, such as:
$f3->route('GET /brew.json','Brew->json');
$f3->route('GET /brew.html','Brew->html');
Then it won't work because PHP won't pass the request to index.php
.In that case, you need to call a custom router, such as the .htrouter.php
you were trying to use. The only thing is that your .htrouter.php
has obviously been designed for a different framework (F3 doesn't care about $_GET['url']
but cares about $_SERVER['SCRIPT_NAME']
.
Here's an exemple of .htrouter.php
that should work with F3:
// public directory definition
$public_dir=__DIR__.'/public';
// serve existing files as-is
if (file_exists($public_dir.$_SERVER['REQUEST_URI']))
return FALSE;
// patch SCRIPT_NAME and pass the request to index.php
$_SERVER['SCRIPT_NAME']='index.php';
require($public_dir.'/index.php');
NB: the $public_dir
variable should be set accordingly to the location of the .htrouter.php
file.For example if you call:
php -S 0.0.0.0:8090 -t public/ .htrouter.php
it should be $public_dir=__DIR__.'/public'
.But if you call:
cd public
php -S 0.0.0.0:8090 .htrouter.php
it should be $public_dir=__DIR__
. PhpStorm give error when run say Built-in web server is only available since PHP 5.4
Just download latest version of XAMPP and install that. It will start working fine after reconfiguration.
Related Topics
Resource Interpreted as Image But Transferred with Mime Type Text/HTML - Magento
What Is an Appropriate Content-Type Header for JavaScript Files
How to Get the Root Url of the Site
Upload Progress Using Pure PHP/Ajax
Sort Array Based on the Datetime in PHP
PHP Redirect with Http Query String Variables
Reverse Letters in Each Word of a String Without Using Native Splitting or Reversing Functions
Add Some Attribute Values to Woocommerce Variable Product Title from Chosen Variation
How to Add Filter or Hook for "Woocommerce_Add_To_Cart"
Laravel Errno 150 Foreign Key Constraint Is Incorrectly Formed
"Call to Undefined Function" Error When Calling Class Method
Moving Array Element to Top in PHP
How to Remove Backslash on JSON_Encode() Function
Replace Any Url's Within a String of Text, to Clickable Links with PHP
Make Woocommerce Checkout Phone Field Optional Based on Shipping Country
Check If a String Is All Caps in PHP