ramblings on PHP, SQL, the web, politics, ultimate frisbee and what else is on in my life
back

URL rewriting

I just tweaked the URLs to specific messages on my blog quite a bit. The URLs that were previously generated as follows:


<?php
// http://pooteeweet.org/blog/__/__/_MAIN_/mode/thread_show/thread_id/348/message_id/388
Param_WWW::generate(array('system' => array('pid' => 'blog'), 'MAIN' => array('mode' => 'thread_show', 'thread_id' => $thread_id, 'message_id' => $message['message_id'])))
?>

Is now just:


<?php
// http://pooteeweet.org/blog/348/388
Param_WWW::generate(array('system' => array('pid' => 'blog')), array($thread_id, $message['message_id']));
?>

This is all done using a simple page level script:


<?php
if (isset($param['fixed'][0]) && is_numeric($param['fixed'][0])) {
    if (isset($param['fixed'][1]) && is_numeric($param['fixed'][1])) {
        $param['MAIN']['message_id'] = $param['fixed'][1];
    }
    $param['MAIN']['mode'] = 'thread_show';
    $param['MAIN']['thread_id'] = $param['fixed'][0];
}
?>

Maybe I should explain a bit about the "wierd" URLs in the WebBuilder2 framework that is used to power this site. The idea is that every page can be defined to use one of many "frame templates" which look something like this.

In those templates you can see a few echo statements. These usually output internal variables as well as the output of modules. In the example I linked above all module output is contained in variables with all capital letters.

Now the idea with the URLs in the WebBuilder2 is that all parameters can either be directed at "system" or one of the modules. In the first URL above we pass a page ID "blog" to the system and then a few parameters to whatever module is configured for the "MAIN" section of the frame template for the page "blog".

Due to this separation we can reorder the modules in the frame template as needed. We can have multiple instances of the same module on the same page. For example the "sitemap" module can produce both a simple navigation on the sidebar along with a full sitemap in the center. Also there is no problem with multiple modules using the same parameter names.

In order to ease URL generation we created a set of classes that can generate URLs, or rather parameter strings and then parse them. This system allows us to switch between using mod_rewrite rules powered URLs and GET URL's with a single switch. But it also allows us to parse parameters from the shell and use the same modules to generate output. We have even used this to execute modules based on emails the system received.

The class that handles URL generation and parsing can be found here. Now the cool thing is that this class also supports "fixed" parameters. The idea being that for example we have defined on the system level that the first parameter is always the page ID. This is why URL's like the following work:
http://pooteeweet.org/blog

Internally this means:


<?php
$params['system']['pid'] = 'blog'
?>

The same can be done for module parameters like I did in the second URL generation example above. Using the script after that I can reorganize the parameters on a page by page basis. The config script above handles the page "blog". So I can keep my URLs nice and short but I need not worry about that in my module. Its all done in a config script.

So the conclusion is:
The WebBuilder2 makes it possible to direct parameters at variables in frame templates. This makes it possible to organize the output of modules in any way you can imagine, prevents variable name clashes between modules and lets you run the same modules from the shell, www or any other way you can call PHP. The parameter strings can easily be generated and parsed with a set of standard classes. Furthermore they can be scripted to be reduced to the bare minimum of information required.

Comments



Re: URL rewriting

Nice little class.

My sample say:
Fatal error: Call to undefined function: array_merge_replace() in ...\ParamHandler\WWW.php on line 338

/Georg

Re: URL rewriting

Ah yes. Its a function we implemented in userland because PHP internals would not accept our contribution in C :(

I will add it to the package.


<?php
    // does not yet exist
    if(!function_exists('array_merge_replace')) {
        function array_merge_replace($a1, $a2)
        {
            if (!is_array($a1) || !is_array($a2)) {
                return false;
            }
            foreach($a2 as $key => $val) {
                if (is_array($val)
                    && isset($a1[$key])
                    && is_array($a1[$key])
                ) {
                    $a1[$key] = array_merge_replace($a1[$key], $val);
                } else {
                    $a1[$key] = $val;
                }
            }
            return $a1;
        }
    }
?>

Re: URL rewriting

I should mention that I also created a proposal for this package in PEAR yesterday:
http://pear.php.net/pepr/pepr-proposal-show.php?id=392

There is even a PEAR installable tgz linked in that proposal. The current version is:
http://pooteeweet.org/pear/ParamHandler-0.1.1.tgz