我已经有一个匹配此模式的路由方法:
/hello/:name
将名称设置为动态路径,我想知道如何制作它:
/hello/{name}
使用相同的正则表达式。如何添加可选的尾部斜杠,像这样?
/hello/:name(/)
or
/hello/{name}(/)
这是我用于/hello/:name
@^/hello/([a-zA-Z0-9\-\_]+)$@D
正则表达式是从PHP类自动生成的
private function getRegex($pattern){
$patternAsRegex = "@^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($pattern)) . "$@D";
return $patternAsRegex;
}
如果路线是/hello/:name(/)
我希望它与可选项匹配,则继续正常
答案 0 :(得分:6)
这将为$pattern
路由创建一个包含:name
和{name}
参数的正则表达式,以及可选的斜杠。作为奖励,它还会添加?<name>
以使参数更容易处理。
例如,/hello/:name(/)
的路由模式将获得正则表达式@^/hello/(?<name>[a-zA-Z0-9\_\-]+)/?$@D
。与匹配的网址匹配,例如preg_match( <regex above>, '/hello/sarah', $matches)
,即$matches['name'] == 'sarah'
。
在实际功能下面有一些测试。
function getRegex($pattern){
if (preg_match('/[^-:\/_{}()a-zA-Z\d]/', $pattern))
return false; // Invalid pattern
// Turn "(/)" into "/?"
$pattern = preg_replace('#\(/\)#', '/?', $pattern);
// Create capture group for ":parameter"
$allowedParamChars = '[a-zA-Z0-9\_\-]+';
$pattern = preg_replace(
'/:(' . $allowedParamChars . ')/', # Replace ":parameter"
'(?<$1>' . $allowedParamChars . ')', # with "(?<parameter>[a-zA-Z0-9\_\-]+)"
$pattern
);
// Create capture group for '{parameter}'
$pattern = preg_replace(
'/{('. $allowedParamChars .')}/', # Replace "{parameter}"
'(?<$1>' . $allowedParamChars . ')', # with "(?<parameter>[a-zA-Z0-9\_\-]+)"
$pattern
);
// Add start and end matching
$patternAsRegex = "@^" . $pattern . "$@D";
return $patternAsRegex;
}
// Test it
$testCases = [
[
'route' => '/hello/:name',
'url' => '/hello/sarah',
'expectedParam' => ['name' => 'sarah'],
],
[
'route' => '/bye/:name(/)',
'url' => '/bye/stella/',
'expectedParam' => ['name' => 'stella'],
],
[
'route' => '/find/{what}(/)',
'url' => '/find/cat',
'expectedParam' => ['what' => 'cat'],
],
[
'route' => '/pay/:when',
'url' => '/pay/later',
'expectedParam' => ['when' => 'later'],
],
];
printf('%-5s %-16s %-39s %-14s %s' . PHP_EOL, 'RES', 'ROUTE', 'PATTERN', 'URL', 'PARAMS');
echo str_repeat('-', 91), PHP_EOL;
foreach ($testCases as $test) {
// Make regexp from route
$patternAsRegex = getRegex($test['route']);
if ($ok = !!$patternAsRegex) {
// We've got a regex, let's parse a URL
if ($ok = preg_match($patternAsRegex, $test['url'], $matches)) {
// Get elements with string keys from matches
$params = array_intersect_key(
$matches,
array_flip(array_filter(array_keys($matches), 'is_string'))
);
// Did we get the expected parameter?
$ok = $params == $test['expectedParam'];
// Turn parameter array into string
list ($key, $value) = each($params);
$params = "$key = $value";
}
}
// Show result of regex generation
printf('%-5s %-16s %-39s %-14s %s' . PHP_EOL,
$ok ? 'PASS' : 'FAIL',
$test['route'], $patternAsRegex,
$test['url'], $params
);
}
输出:
RES ROUTE PATTERN URL PARAMS
-------------------------------------------------------------------------------------------
PASS /hello/:name @^/hello/(?<name>[a-zA-Z0-9\_\-]+)$@D /hello/sarah name = sarah
PASS /bye/:name(/) @^/bye/(?<name>[a-zA-Z0-9\_\-]+)/?$@D /bye/stella/ name = stella
PASS /find/{what}(/) @^/find/(?<what>[a-zA-Z0-9\_\-]+)/?$@D /find/cat what = cat
PASS /pay/:when @^/pay/(?<when>[a-zA-Z0-9\_\-]+)$@D /pay/later when = later
答案 1 :(得分:1)
只需将此正则表达式替换为可选的(a, Float, Float)
:
@^/hello/([a-zA-Z0-9-_]+)/?$@