gpt4 book ai didi

php - 如何为路由框架做 URL 匹配正则表达式?

转载 作者:行者123 更新时间:2023-12-03 23:23:29 33 4
gpt4 key购买 nike

我已经有一个匹配这个模式的路由方法:

/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(/)我希望它与其他可选的东西相匹配继续正常

最佳答案

这将为 $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
);
}

输出:
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

关于php - 如何为路由框架做 URL 匹配正则表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30130913/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com