我在制作自己的一个正则表达式时遇到很多困难以满足我的需求。 这是一个我试图不使用框架的应用程序,除了Doctrine,但在这种情况下并不重要。我正在使用Front Controller模式,并使用注释将路由映射到控制器的方法。
像:
/**
* @GetMethod
* @Route(name=index)
* @return UserProfileDto
*/
public function getUserProfile();
任何人都可以帮助制作一个正则表达式以匹配我需要的所有内容吗?
规则是:
必填:
可选:
这是我设法做的事情:
<?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);
?>
答案 0 :(得分:3)
我会使用单个正则表达式来验证/匹配整个路由字符串,并从返回的$ matches数组中提取控制器,操作,参数和类型。之后可以解析参数部分,其可以具有可变数量的部分。这是一个经过测试的PHP脚本,带有注释的正则表达式,应该是一个非常好的起点:
<?php // test.php Rev:20121105_1900
$route = '/controller/action/param1/param2/param3.html';
$re = '%
# Parse controller, action, params and type from route.
^ # Anchor to start of string.
/ # $controller prefix (required).
(?P<controller> # $controller (required).
[^/\\\\.]+ # Value = one or more non-/\..
) # $controller (required).
(?: # Action is optional.
/ # $action prefix.
(?P<action> # $action.
[^/\\\\.]+ # Value = one or more non-/\..
) # $action.
)? # Action is optional.
(?: # Parameters are optional.
(?P<params> # $params.
(?: # One or more parameters
/ # Params separated by a /.
[^/\\\\.]+ # Value = one or more non-/\..
)+ # One or more parameters
) # $params.
)? # Parameters are optional.
\. # $type prefix (required).
(?P<type> # $type (required).
[^/\\\\.]+ # Value = one or more non-/\..
) # $type (required).
$ # Anchor to end of string.
%x';
if (preg_match($re, $route, $matches)) {
// Valid route string.
printf("OK: \"%s\" is a valid route string.\n", $route);
printf( " controller = \"%s\"\n", $matches['controller']);
printf( " type = \"%s\"\n", $matches['type']);
if ($matches['action']) {
printf( " action = \"%s\"\n", $matches['action']);
} else {
printf( " action = (none)\n");
}
if ($matches['params']) {
printf( " params = \"%s\"\n", $matches['params']);
$params = preg_split('%/%', $matches['params'], -1, PREG_SPLIT_NO_EMPTY);
for ($i = 0; $i < count($params); ++$i) {
printf( " p[%d] = \"%s\"\n", $i+1, $params[$i]);
}
} else {
printf( " params = (none)\n");
}
} else {
// Not a valid route string.
printf("ERROR: \"%s\" is NOT a valid route string.\n", $route);
}
?>
OK: "/controller/action/param1/param2/param3.html" is a valid route string.
controller = "controller"
type = "html"
action = "action"
params = "/param1/param2/param3"
p[1] = "param1"
p[2] = "param2"
p[3] = "param3"
答案 1 :(得分:0)
您可以使用explode()
示例:
$url = "/profile/edit/23.html";
$parsed = explode("/",$url);
现在$ url的每个元素都在解析的数组中:
$objRoute->controller = $parsed[1];
$objRoute->action = $parsed[2];
...
$解析的转储将为您提供:
"" // blank
"profile" // controller
"edit" // action
"23.html" // values