Front Controller/Modrewrite
Introduction
To achive rapid development with web applications it is critical to use the same directory structure for all your projects. The most important part of this tutorial is that it will show you how to seperate the design from logic. I will not outline any template systems that are available in this tutorial I have just implemented a simple text replace template. Also we will not be going into the object structure of a front controller pattern. These are things you can look up for yourself on the net or read any good Object Patterns book.
The main point of this tutorial is to highlight the magic of the modrewrite module and show how you can use it to make a Dreamweaver safe development environment. What do I mean by Dreamweaver safe? Well If we assume most professional designers like to use Dreamweaver, wouldn't it be nice to give them a folder they can work in without affecting your php code? This would also mean the developer would no longer have to be called on if a phone number changed.
The issues addressed with this particular modrewrite tutorial is to provide an elegant solution to accessing the css/js/images (media) from your code without copying the images out of the html template folder to the site root folder. This might sound trivial but it gives the designer the ability to add/remove media in the html folder where Dreamweaver can access it for its internal rendering. If you are lost on this explanation but like the idea of using modrewrite and a Front Controller read on...
The Front Controller
What is meant by a Front Controller. This is a term used to describe a common place that all page requests are passed through before processing begins. This is ideal to setup your application environment (database connections, .ini configurations, etc). We will be using it to take the request and manipulate it to find the corresponding template. Once the template is found we then process it and then render it.
This basic implementation of a front controller is by no way meant to be a solution to use for a real world project. It is good for this tutorial to outline the modrewite/template solution. Look at the site PHPPatterns if you wish to learn more about the Front Controller pattern.
Lets a have a quick look at the index.php.
- First we need to get the requested file from the request uri. We then translate that to the file path of the template in the html folder so we can read it into memory.
- Next we read in the fresh template. Then we decide what content is to be rendered or render an error if no content found.
- Finally render the page to the browser.
/index.php
// 1. Get the request URI
$requestUri = $_SERVER['REQUEST_URI'];
$htdocRoot = $_SERVER['PHP_SELF']; // Will always be the index.php file
$baseFile = 'index.html';
if (is_file($requestUri)) {
$baseFile = basename($requestUri);
} else {
$baseFile = "error.html";
}
$tpl = dirname(__FILE__) . "/html/$baseFile";
// 2. Render correct content to the new template
$html = file_get_contents($tpl);
$html = renderNav($html);
switch ($baseFile) {
case 'index.html':
$html = renderIndex($html);
break;
default:
$html = renderError($html);
break;
}
// 3. Display
echo $html;
I would hope you can create a better Front Controller to handle a wider range of situations.
The template is just a string replace of a comment tag like <!-- @CONTENT@ -->, I assume most template systems could be modified to handle this directory structure. In future tutorials I will be introducing the concept of creating a XML/XHTML PHP DOM Template system that is a great solution for enteprise PHP applications built in a team environment and works perfect for the structure in this tutorial.
Modrewrite And Apache
We use the modrewrite module to port all requests through to the 'index.php' file. We also ignore all known media types to allow for downloading like images and other media.
/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# 1. Apply rule to all web pages eg html, php, htm
RewriteRule !\.(swf|zip|tar|tar|pdf|doc|txt|js|ico|gif|jpg|png|css)$ index.php [NC,L]
# 2. Rewrite all media in the html folder
RewriteCond %{REQUEST_URI} !^(.*)/lib/(.*)$ [NC]
RewriteRule css/(.*) html/css/$1 [L]
# 3. Rewrite all media in the html folder
RewriteCond %{REQUEST_URI} !^(.*)/lib/(.*)$ [NC]
RewriteRule js/(.*) html/js/$1 [L]
# 4. Rewrite all media in the html folder
RewriteCond %{REQUEST_URI} !^(.*)/lib/(.*)$ [NC]
RewriteRule images/(.*) html/images/$1 [L]
</IfModule>
First we test to see if the modrewite module exsits. If it does turn it on. To see an example of how to turn it off see the /doc/.htaccess file. The parameter 'RewriteBase' is very important. It must be set to the http root (HTDOC_ROOT) of the project with a trailing slash, this should be done to get the example files working also.
Next we check the request and make some logical desisions:
- First we check if the requested file is any of the media types if not we forward off the request to the index.php file. This is then processed and rendered to the browser.
- Next we look for all requests going to the css folder we then translate a request like '/css/base.css' to '/html/css/base.css' however if a request is sent to the '/lib/css/lib.css' the request remains unchanged this is done using the 'RewriteCond' directive. 3 And 4 are the same but for the folders images and js.
One important thing to note is that I have a .htaccess file in the lib folder. This is to deny public access to included lib files. but if you look in the '/lib/css/' folder there is a .htaccess file giving permission to read if it wasn't there we would not be able publicly read the css folder. The same should be done to any parent folder in the lib directory that you wish to give public access. Don't forget! it could cost you time in trying to figure out why your images arn't loading...
Putting it all Together
Now we have a basic front controller and a modrewite file we need a sane directory structure that we can use for all our projects. I use the following structure you can create your own but be sure to update the .htaccess modrewrite directives to reflect the modified direcotry names.
/project-root
|
|-> /html --> Template Files
| |
| |-> /css -|
| |-> /images |--> Media files
| |-> /js -|
| |-> /Templates --> Dreamweaver Templates
| |-> error.html
| |-> index.html
|
|-> /lib --> Project include files
| |
| |-> /css
| |-> ...
|
|-> /.htaccess --> Modrewrite code here!!!
|-> /index.php --> Execute Front Controller here!!!
|
From this directory structure you and your team will become familiar with all future projects and using an if you use an SVN code repository you can store template projects that could be a base for your future projects.
Summing It Up
If you are looking for a way to impress your designer mates then this is it. If you are the only developer that can offer them their own area in a project to work, and rarely gets modified by outside developers they will be delighted I am sure.
Download
You can download the tutorial files from example1.zip