PHP is a both a front-end and back-end scripting language. If you've also used PHP for both ends of a full-stack application, you might relate to the frustration of looking for a free, high-quality local development tool for full-stack PHP developers.
With JavaScript, you can start a server directly in code, choose the port, and rewrite the urls without hassle, using Node's core http module.
Similarly, Java supports the feature through, for example, Sun's NET HttpServer package and C# as well.
But PHP is different from other languages. To start up the built-in web server, you use the following command:
php -S localhost:8000
Unfortunately, this creates only a very basic server that cannot rewrite files or interact with a database easily.
To resolve this, the recommended approach for hobbyists like myself is to use an Apache distribution:
- XAMPP
- WAMPServer
- LAMP (Linux)
The above are all tech stacks with PHP, MySQL, and Apache. The Apache server will read the .htaccess
file before serving a page, which means you can make more user-friendly URL names.
The Problem
And now comes a problem. You can only run one server at a time using Apache, so let's say you choose the front-end.
What do you do with the back-end? My initial reaction when trying this out myself was to use the PHP command for this.
This works, only partly. The REST API also uses url rewrites on the live server, and I want to make it as close as possible so I can minimize or even eliminate "development mode" conditionals.
The Solution
The solution is to use a router.php
file. Here's an example:
<?php
chdir(__DIR__);
$filePath = realpath(ltrim($_SERVER["REQUEST_URI"], '/'));
if ($filePath && is_dir($filePath)){
// attempt to find an index file
foreach (['index.php', 'index.html'] as $indexFile){
if ($filePath = realpath($filePath . DIRECTORY_SEPARATOR . $indexFile)){
break;
}
}
}
if ($filePath && is_file($filePath)) {
// 1. check that file is not outside of this directory for security
// 2. check for circular reference to router.php
// 3. don't serve dotfiles
if (strpos($filePath, __DIR__ . DIRECTORY_SEPARATOR) === 0 &&
$filePath != __DIR__ . DIRECTORY_SEPARATOR . 'router.php' &&
substr(basename($filePath), 0, 1) != '.'
) {
if (strtolower(substr($filePath, -4)) == '.php') {
// php file; serve through interpreter
include $filePath;
} else {
// asset file; serve from filesystem
return false;
}
} else {
// disallowed file
header("HTTP/1.1 404 Not Found");
echo "404 Not Found";
}
} else {
// rewrite to our index file
include __DIR__ . DIRECTORY_SEPARATOR . 'index.php';
}
I then ran php -S localhost:8100 router.php
in the root directory of my API.
Conclusion
And Voila! I was able to communicate between the front-end and back-end server without needing to deploy until I was ready!
Here is the StackOverflow question that helped to this solution: https://stackoverflow.com/questions/27381520/php-built-in-server-and-htaccess-mod-rewrites
I hope you found this post useful. Do you know any alternatives or easier ways to accomplish the same task? Leave a comment down below!
Top comments (0)