我在制作自己的一个正则表达式来满足我的需求时遇到了很多麻烦。这是一个我试图不使用框架的应用程序,除了 Doctrine,但在那种情况下并不重要。我正在使用前端控制器模式,并使用注释将我的路由映射到控制器的方法。
像:
/**
* @GetMethod
* @Route(name=index)
* @return UserProfileDto
*/
public function getUserProfile();
任何人都可以帮助制作一个正则表达式来匹配我需要的一切吗?
规则是:
必需的:
- 控制器( /controller,url 上的第一项)
- 类型(.json、.xml、.html、...)
选修的:
- 操作(/controller/action,url 上的第二项)
- 参数(动作和类型之间的一切,/controller/action/param1/param2/param3.type)
这是我设法做到的:
<?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);
?>