Structure
A Front controller usually consists of a request handler and a command dictionary. The request handler receives requests from the web server and then dispatches the request to a command in its dictionary that will handle the request. The dispatch process can be delegated to an Application Controller.
The Front Controller may also package web server specific data structures into a Context Object to shield subsequent commands from web server details.
Registering a request handler with the Apache Web Server
The Front Controller must be registered with the web server.
A web applicaton may have more than one Front Controller. If a web application uses more than one front controller, each one must be registered with the web server.
Physical mapping
Apache uses a physical mapping technique to map URLs to a physical files. The easiest way to register a FrontController with apache is to move physical file into the ~DocumentRoot directory. Assuming a DocumentRoot of /home/user/public_html, apache will map http://www.mydomain.com/index.php?category=fish to the file /home/user/public_html/index.php.
To make the previous URL look friendlier to both search engines and to surfers, you can take advantage of the fact that apache stops parsing an url as soon as it has found a file to handle it. Thus apache will also map the following url to the same file:
The /fish/ portion of this url is not used for locating the physical file because the file has already been found before that segment of the url is processed.
If you are unhappy with the index.php in your url, you can take advantage of mod_mimes, ForceType directive. First, rename index.php to category with no extension. Then add the following to your .htaccess or apache config file:
<Files category>
ForceType application/x-httpd-php
</Files>
Because it has no extension, this is required to force apache to use php interpret the category file. This would then make the url into:
See Using ForceType for Nicer Urls
Logical Mapping with mod_rewrite
Another technique is to use mod_rewrite. mod_rewrite can map arbitrary Urls into physical files.
RewriteEngine On
RewriteRule !^(css|images|files)/ index.php [NC,L]
The above will “route” all requests, except those containing css, images or files (for those subdirectories) through index.php without requiring index.php to appear in the URL. Routing requests through a single entry point became a common approach for organizing URLs and request handling in many web applications.
Logical Mapping with "ErrorDocument"
One last technique is to use apache's ErrorDocument directive. This relies on apache NOT finding a physcial file to match your request and calling your Front Controller, which is registered with the ErrorDocument directive. Instruct Apache with;
ErrorDocument 404 /frontcontroller.php
For more information see Half baked and a little fried and Funky Caching - although the techniques described in these links relates to caching output, it can be applied equally to creating a Front Controller.
Dispatching Techniques
A Front Controller may delegate command dispatching to an Application Controller.
Static Invocation
Static invocation uses conditional logic to determine which command to execute. This is an old PHP pattern and the simplest way to implement a front controller, although not very scalable.
switch ($_GET['op']) {
case 'view':
View($context);
break;
case 'delete':
Delete($context);
break;
...
}
Dynamic Invocation
In this style, the command to handle the request is dynamically calculated based on the request inputs. This has two advantages. First, new commands can be added by placing a file into a special location in the file structure. Second, It is fairly efficient.
Here is an example from the PHP-Nuke module.php front controller:
if (!isset($file)) { $file="index"; }
...
$modpath .= "modules/$name/$file.php";
if (file_exists($modpath)) {
include($modpath);
} else {
die ("Sorry, such file doesn't exist...");
}
A different approach is done by BTPL2: In BTPL2, all pages consist of several boxes - each box of some class, provided by some module. One of the most central box classes is the loader-box, whichs takes an special URI parameter as a key to select the desired box (and all its parameters) from the loader's boxtable. The datasource for this boxtable can be some datasource, from a simple ascii text to a database query. For example our page has got an loader-box in the middle tray and uses “load” as selector. Also we've got this box-config record:
:name: welcome
:module: box.display
:template-file: pages/welcome/content.template
:template-name: content
So an request to ./?load=welcome would then dispatch to the module box.display (./modules/box.display/box_display.inc) and the whole box record as shown above would be given to the module code.
Lookup Invokation
Uses a lookup operation to determine which command to execute. Sometimes uses a configuration file to load the lookup table. see Centralized Configuration File Anti-Pattern