PHP Framework II: Page Request Dispatcher

18.02.2009 • 23:24 • permalinkComments (0)

Having built the foundation for working with the database I move on to the main logic of dispatching page requests. The strategy I have used is to treat the retrieval of pages as a RESTful API where the request url becomes a parameter to a dispatcher.

Rather than having the url hiearchy of the website map directly to the server-side file hierarchy, all requests are routed through a single php file using url rewriting. This can be done simply by modifying the .htaccess file like this:

  1. #Options +FollowSymlinks
  2. RewriteEngine on
  3.  
  4. RewriteRule \.(js|ico|gif|jpg|JPG|png|css|txt|xml)$  -  [L]
  5. RewriteRule ^(.*)$ index.php

The .htaccess file is configured to allow image files and other such resources through as normal. You can also allow other types of files to be treated as normal by adding their extension to the list. For a great introduction to all the useful things you can do with the .htaccess file, click here.

The main purpose of the dispatcher is to pick the requested url apart and ask the proper components to construct a response view. Speaking of views, I use the MVP pattern to split up the responsibility of the components. Thus, each first level subdirectory of the website matches a controller instance which handles validation and presentation of the view. When you request an url, the dispatcher checks for the existance of a controller class with the name of the subdirectory. If one such exists, the remainder of the url is passed to it as a parameter to validate whether it is a legal url. To illustrate how this work, consider the following url to a blog post on this site:

  1. http://www.without-precedence.dk/blog/01-02-09/renaissance

The blog part of the url tells the dispatcher that it should look for a class called BlogController in a file called blog.php. All controllers implement the IController interface which provides a method for validating the url and presenting the view.

  1. interface IController{
  2.     public function show($param);
  3.     public function validateParam($param);
  4. }

The rest of the url contains a date and an url-encoded blog title. These are first passed to the validateParam method to make sure the post exists and then to the show method to render the blog post.

If no controller is found or the controller does not validate the url, the standard error page is shown - which is just another controller being invoked. Controllers can also be made to handle urls which does not correspond to normal pages such as AJAX requests and file downloads. This design is what I was referring to when I was talking about the RESTful API, where each url request can be seen as an API call that can be handled in an arbitrary fashion.

Whenever you want another sub-page or provide some service (such as RSS feeds, the creation of which I will be blogging about in the not too distant future) you must simply create a controller with the proper file and class-names and you're in business. This might be simplifying things a bit, as you would most likely need to also create a model class and a view class to interact with the database and construct the page view, respectively, but I'm sure you'll forgive that minor slight.

On a final note, this design might not be ideal for handling deeply nested urls, as the controllers can become very complex but there's nothing stopping you from implementing a nested controller structure. I ran into a spot of trouble when I attempted to create a sub-hierarchy of admin pages within a single controller, which I can't recommend.

The framework code has been updated to contain the functionality described in this post and it can be found here.

Comments

Name:

Comment (no HTML):