Recent changes RSS feed
 

Front Controller

A front controller presents a single point for a web server to interface with a web application.

A Front controller is a pattern for Centralized Request Logic. A front controller can help eliminate duplicate code on a series of requests by routing the requests through the front controller and factoring the duplicate code from the requests into the front controller.

A front controller can help to encapsulate the differences in how an application registers itself with the web server. With a front controller, only the front controller need be registered. This makes the web application more portable between web servers and can save time if the web server is difficult to configure. (Is this more of an issue with Java than it is with PHP?)

A front controller can help implement the Intercepting Filter pattern.

Because many different requests pass through the front controller, it can be performance sensitive. Placing logic in the front controller which is not used for all requests will add unnecessary overhead to some requests.

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:

http://www.mydomain.com/index.php/fish/

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:

http://www.mydomain.com/category/fish/

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. So a URL like http://www.mydomain.com/category/fish/ will have category/fish/ passed through index.php and made available with $_SERVER['REQUEST_URI']. More advanced uses of mod_rewrite could take advantage of its RewriteCond directives to test if a request maps to a file, directory, symlink.

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...");
}

The following Url http://phpnuke.org/modules.php?name=FAQ&myfaq=yes&id_cat=1&categories=PHP-Nuke+General+Info is dispatched to /home/user/public_html/modules/FAQ/index.php

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

Additional Information

 
pattern/front_controller.txt · Last modified: 2007/07/07 07:30 by xolox
 
Hosting for this site donated by Procata PHP Development