I am trying to build a router function to properly match incoming URI’s and match them to an array of stored system URI’s. I also have wildcards ‘(:any)’ and ‘(:num)’ similar to CodeIgniter.
Basically, I am trying to get the ‘admin/stats/(:num)’ entry to match on both ‘admin/stats’ and admin/stats/1′.
While the script is starting I grab all paths from a separate array and use a foreach to save each path:
route('admin/stats/(:num)', array('#title' => 'Statistics',...));
The function is:
function route($path = NULL, $options = NULL) {
static $routes;
//If no arguments are supplied, return all routes stored.
if(!isset($path) && !isset($options)) {
return $routes;
}
//return options for path if $path is set.
if(isset($path) && !isset($options)) {
//If we have an exact match, return it.
if(array_key_exists($path, $routes)) {
return $routes[$path];
}
//Else, we need to use RegEx to find the correct route options.
else {
$regex = str_replace('/', '\/', $path);
$regex = '#^' . $regex . '\/?$#';
//I am trying to get the array key for $route[$path], but it isn't working.
// route_replace('admin/stats/(:num)') = 'admin/stats/([0-9]+)'.
$uri_path = route_replace(key($routes[$path])); //route_replace replaces wildcards for regex.
if(preg_match($regex, $uri_path)) {
return $routes[$path];
}
}
}
$routes[$path] = $options;
return $routes;
}
Route replace function:
function route_replace($path) {
return str_replace(':any', '.+', str_replace(':num', '[0-9]+', $path));
}
A key/value pair in the $routes array looks like:
[admin/stats/(:num)] => Array
(
[#title] => Statistics //Page title
[#access] => user_access //function to check if user is authorized
[#content] => html_stats //function that returns HTML for the page
[#form_submit] => form_stats //Function to handle POST submits.
)
Thanks for the help. This is my first router and I am not that familiar in making proper Regex’s.
‘admin/stats/(:num)’ will never match ‘admin/stats’ as in your “pattern” the slash is required. In pseduo-regex you need to do something like ‘admin/stats(/:num)’.
There does also seem to be a few bugs in your code. This line
is in the block that is executed when $path is not a key that exists in $routes.
I’ve tried to rewrite it and this seems to work (this is just the else clause):
But this requires ‘admin/stats/(:num)’ to be ‘admin/stats(/:num)’.
btw if you don’t have one already, you should get a debugger (Zend and xDebug are two of the most common ones for PHP). They can be invaluable in solving problems like this.
Also, ask yourself if you need to write a router, or whether you can’t just use one of the perfectly good ones out there already…