I’ve been using Comb, my experimental PHP framework, for a couple of super-secret projects over the past few months (on those sporadic occasions when I actually write code), and it’s been evolving pretty dramatically. So much so that very little of the original code still exists. I’m still calling it “Comb” though, because the underlying idea is still the same. It’s too time consuming to describe the reasons why I changed each part, so suffice it to say the changes are essentially organizational. Instead I’ll just jump into explaining it from the ground up as it exists now.

To begin with, here’s the now-simplified Apache VirtualHost container that I’m using:

1
2
3
4
5
6
7
8
9
10
11
<VirtualHost *:80>
    ServerName      example.com
    DocumentRoot    /vhosts/example.com/www
    ErrorDocument   404 /404.php
 
    <Directory "/vhosts/example.com/www">
        AllowOverride All
        php_value include_path ".:/vhosts/example.com/www/lib:/vhosts/lib"
        php_value auto_prepend_file /vhosts/example.com/www/comb.php
    </Directory>
</VirtualHost>

The first four lines should be pretty self-explanatory, but for the rest:

  1. Allow the full use of .htaccess files, e.g., for rewrite rules, etc
  2. Set PHP’s include_path to the current working dir (when parsing templates), the application’s lib dir (for app-specific classes), and the system lib dir (for shared classes)
  3. Prepend comb.php in the document root to every requested PHP script.

This Apache configuration ensures that every requested script will first run the site’s comb.php script, which is a very simple, application-agnostic bootstrap script, meaning it’s basically the same for every app that I build. In fact I could just have one copy of it in a central directory and prepend it from there, but I’d lose some potential flexibility that way. Though that could probably be coded around. Anyway, here’s where things get interesting… comb.php looks like this:

1
2
3
4
5
6
7
<?php
    require '/www/include/load.php';
    spl_autoload_register('load');
 
    $comb = new util_comb();
    $comb->run();
    $comb->send();

My standard autoloader is pretty simplistic; it just converts “util_comb” into “util/comb.php” and tries to include it based on the include_path set in the vhost container.

The util_comb class encapsulates all the crucial routing and response rendering logic. The constructor parses the request URI into its segments and loops over them looking for any files called prepend.php and append.php. If they exist, they’re added into an array that I refer to as the inclusion list. To visualize this, imagine a request for /user/profile.php?name=drew. The vhost will start by running comb.php, and the following scripts will get added to the inclusion list if they exist:

/prepend.php
/user/prepend.php
/user/profile.php
/user/append.php
/append.php

…in that order. The idea is to sort of mimic the way Apache finds and parses .htaccess files that are (possibly) in each subdirectory.

The next method that’s called, $comb->run(), simply loops over the inclusion list and include()s each one of them.

Finally, $comb->send() is called, in which the response is created and sent. This is where template rendering or redirecting takes place.

My next few blog entries will go into the details of the inclusion list, how I’ve set up template rendering, and how to get clean/friendly URLs working.

Over the past few months I’ve been adding code to this previously unnamed LAMP framework, but I’ve honestly been reluctant to call it a framework. That’s what it is though, so instead of constantly referring to it as “my little minimalist pseudo-framework”, I decided to give the thing a name. I’ve been mulling it over for several months now, and finally settled on Camber as the name. I wanted to be sure that it was easy enough to remember, but also meaningful to the overall goal of the project. According to Google:

Camber: The curvature of a structural member for the purpose of offsetting the deflection when loads are applied.

Camber is not a complex idea, nor is it difficult to implement where it’s needed. It’s used in many everyday load-bearing applications; the wheels of a car, the shape of skis and snowboards, the bottom of a bridge, the shape of a wing. The performance of each of these is greatly enhanced – if not utterly dependent – on something as simple as the underlying negative curvature.

Sounds like a pretty good description of a web application framework, eh?

Unfortunately, I’ve been really slack about keeping this here blog up to date with the actual code I’ve been writing. I have a tendency to drone on and on about each concept of the system, so I think I need to take smaller bites. One post per day maybe, with no more than 2 or 3 snippets of code.

So, picking up from where I left off in Step 3, cleaning up the server-side, we’ve now got a simple HTML form that sends a clean request into the server, and a nice little Request class to make the incoming data easy to work with. To jog your memory, the form looks like:

Read the rest of this entry

Once I had my virtual host set up to route all requests into a single script, I then had to figure out what to do with each request. I knew that the essential request information was available in the $_SERVER autoglobal, but I wanted a cleaner way of dealing with the request. So I put together a very simple Request class, which I saved in the document root as Request.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
< ?php 
class Request 
{ 
    public $method; 
    public $url; 
    public $parameters = array();  
    public function __construct() 
    { 
        $this->method = $_SERVER['REQUEST_METHOD']; 
        $this->url = $_SERVER['SCRIPT_URI']; 
        $this->parameters = $_REQUEST; 
    } 
} 
?>

I then altered index.php to contain the following:

1
2
3
4
5
6
7
8
9
10
< ?php
    include 'Request.php';
 
    $req = new Request();   
 
    echo "Method: {$req->method} <br />";
    echo "URL: {$req->url} <br />";
    echo "Parameters: <code>" . print_r($req->parameters, true) . "</code>";
 
?>

Read the rest of this entry

So why am I bothering with “clean” URLs? For several reasons really. For one thing, they look nicer than un-clean URLs. I would much rather get rid of something like, this:

http://www.example.com/forumDisplay.php?fid=17

and instead use something like this:

http://www.example.com/forum/general

But aesthetics aside, why should I bother? My reason is inspired by Roy Fielding’s REST. I won’t try to get into the guts of it here, partly because there’s alot to it, and partly because my grasp of it is far from complete. Regardless, what I’ve taken from my brief introduction to it is a resolution to build applications from a resource-centric point of view, as opposed to a functional, process-centric point of view. Instead of building a collection of scripts that expect data to be passed in so that they can spit data out, I decided to try to build a system of resources that can be manipulated.

Read the rest of this entry