I'm having a lot of trouble making one single regex of my own to match my needs. It's an application that I'm trying not to use a framework, except Doctrine, but in that case doesn't matter. I'm using Front Controller pattern and I mapping my routes to controller's methods using annotations.
Like:
/**
* @GetMethod
* @Route(name=index)
* @return UserProfileDto
*/
public function getUserProfile();
Can anyone help to make one single regex to match everything I need?
The rules are:
Required:
- Controller ( /controller, first item on the url )
- Type (.json, .xml, .html, ...)
Optional:
- Action ( /controller/action, second item on the url )
- Parameters ( everything between action and type, /controller/action/param1/param2/param3.type )
Here's what I managed to do:
<?php
header("content-type: text/plain");
// example url access: /profile/edit/23.html, /profile/delete/2.json, /profile.xml, /user/list.xml
$string = $_GET['u'];
$matches = array();
$objRoute = new stdClass();
preg_match_all("~^/(?P<controller>[^/\\.]+)~", $string, $matches);
if ($matches && $matches['controller']) {
$objRoute->controller = $matches['controller'][0];
} else {
$objRoute->controller = "index";
}
preg_match_all("~^/$objRoute->controller/(?P<action>[^/\\.]+)~", $string, $matches);
if ($matches && $matches['action']) {
$objRoute->action = $matches['action'][0];
preg_match_all("~^/$objRoute->controller/{$objRoute->action}(?:/[^\\.]+)?\\.(?P<type>.+)$~", $string, $matches);
} else {
preg_match_all("~^/$objRoute->controller\\.(?P<type>.+)$~", $string, $matches);
$objRoute->action = "index";
$objRoute->parameters = null;
}
if ($matches && $matches['type']) {
$objRoute->type = $matches['type'][0];
preg_match_all("~^/$objRoute->controller/{$objRoute->action}(?:/(?P<parameters>[^\\.]+))?\\.{$objRoute->type}$~", $string, $matches);
if ($matches && $matches['parameters'] && $matches['parameters'][0]) {
$objRoute->parameters = explode("/",$matches['parameters'][0]);
} else {
$objRoute->parameters = null;
}
} else {
die("Bad Request, no reponse type provided");
}
// "advanced" example method route @Route(name=edit/{id})
$route = "edit/{id}";
$route = preg_replace("~\\{([^\\}]+)\\}~", '(?P<' . '${1}' . '>[^/]+)', $route);
$routeTo = $objRoute->action . "/" . implode("/",$objRoute->parameters);
if ($objRoute->parameters && count($objRoute->parameters)) {
preg_match_all("~^$route$~", $routeTo , $matches);
}
foreach($matches as $idx => $match) {
if ($match && $match[0] && !is_numeric($idx)) {
$objRoute->{$idx} = $match[0];
}
}
print_r($objRoute);
?>