tags:

views:

718

answers:

3

I am trying to construct a regex based router for a MVC framework I am working on. I was very fond of the way Django handled urls in urls.py, and would like to create something similar. Does anyone have any code / examples of how I can create an array of regular expressions which my router can 'process' to instantiate the controller (or the default controller if one has not been specified), call methods and pass arguments?

Any tips would be really appreciated.

A: 

I've done something similar with bLibrary library. It's designed to take the values after the PHP page in the URL. I'm not sure how to word that so heres how it looks

http://www.example.com/page.php/this/is/a/location-here

The data the script uses is:

/this/is/a/location-here

So then you can chose how to use regular expressions on this string. I usually would just split out the paths using explode and work on the page using that.

The code is here: hosted on google code

null
A: 

Use .htacess

RewriteRule ^(.*)$ index.php?rt=$1 [L,QSA]

and then inside index.php

$url = $_GET['rt'];
$tmp = explode("/", $url);

you can then array_shift $tmp in order to get your controller/action

lemon
+3  A: 

This is perhaps shameless self-promotion, but...

I've written a little framework which (amongst other things) attempts to mimic Django's URL dispatch functionality in PHP. It's not quite done yet (documentation is really minimal right now), but it's getting there... You may find the wiki article on URL dispatching, the URL resolver and invocation code (see also here) helpful.

With that said, here is a little recipe to get you started: Let's say you have a configuration file containing mappings between regular expressions and callbacks:

<?php
return array(
  '{^blog/(?<year>\d+)/(?<slug>[\w-]+)$}' => array('BlogController', 'post'),
  '{^about$}' => array('AboutController', 'about'),
  // and so on...
);

Iterate over this array and match the keys against the request URL:

<?php
foreach($urlconf as $pattern => $callback) {
  if (preg_match($pattern, $_SERVER['REQUEST_URI'], $matches) !== false) {
      return dispatch($callback, $matches); // match
  }
}
return handle_404(); // no match

The dispatch() function should/could instantiate the controller class and and inspect the method using reflection. This would typically involve validating the URL pattern matches with respect to the parameters of the method in question. You would need to collect the arguments with which to invoke the method with: filling in default arguments if present, figuring out which named or positional match correspond to which parameter, etc. (See this code for an example.) Then, the controller method can be invoked using the arguments from the URL pattern match.

Hope this helps!

EDIT: Of course, mod_rewrite or the $_SERVER['PATH_INFO'] trick is needed to send all requests to the same .php file. A suitable .htaccess file can be found here.

Øystein Riiser Gundersen