Moh*_*lal 1 php regex routing match
我已经有一个匹配此模式的路由方法:
/hello/:name
Run Code Online (Sandbox Code Playgroud)
将名称设置为动态路径,我想知道如何制作它:
/hello/{name}
Run Code Online (Sandbox Code Playgroud)
与正则表达式相同.如何添加可选的尾部斜杠,像这样?
/hello/:name(/)
or
/hello/{name}(/)
Run Code Online (Sandbox Code Playgroud)
这是我用的正则表达式 /hello/:name
@^/hello/([a-zA-Z0-9\-\_]+)$@D
Run Code Online (Sandbox Code Playgroud)
正则表达式是从PHP类自动生成的
private function getRegex($pattern){
$patternAsRegex = "@^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($pattern)) . "$@D";
return $patternAsRegex;
}
Run Code Online (Sandbox Code Playgroud)
如果路线是/hello/:name(/)
我希望它与可选的东西进行匹配,则继续正常
这将为$pattern
包含参数:name
和{name}
参数的路径创建正则表达式,以及可选的斜杠.作为奖励,它还将添加一个?<name>
以使参数更容易处理.
例如,路由模式/hello/:name(/)
将获得正则表达式@^/hello/(?<name>[a-zA-Z0-9\_\-]+)/?$@D
.与URL匹配时,就像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
);
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)