我正在尝试创建一个模拟正则表达式模式来过滤类似 Laravel 的路由,但我无法弄清楚我的正则表达式。我想替换路由中的 {variable} 并将其与 uri 匹配。
示例:
路线:
/user/{id}
/user/{id}/edit
URI:
/user/1
/user/1/edit
当前代码(以下代码位于遍历路由的 foreach 循环中)
//escape slashes
$pattern = '/^' . str_replace("/", '\/', $route) . '$/i';
//strip out variables from route to compare with uri
$pattern = preg_replace('/\{(.*?)\}/', '(.*?)', $pattern);
if (preg_match($pattern, $uri)){
echo "Found a match.";
}
问题是,当在浏览器中输入上面的第二个 uri(/user/1/edit) 时,它将与第一个路由匹配,而不是与第二个路由匹配。我假设是因为我用 (.*?) 替换了变量({id}),所以它将匹配变量后面的任何内容。
最佳答案
问题可能是demonstrated as thus (这是一个实际的最小测试用例,请努力创建它们!)
preg_match("{^/(.*?)/(.*?)/$}", "/foo/bar/", $matches);
var_dump($matches); // captures -> "foo", "bar"
preg_match("{^/(.*?)/$}", "/foo/bar/", $matches);
var_dump($matches); // captures -> "foo/bar"
这是因为非贪婪的“?”限定符表示“在仍然尽最大努力进行匹配的同时,尽可能少地匹配可以”。在第二种情况下,正则表达式引擎首先尝试仅匹配“foo”,然后由于模式失败,正则表达式回溯并且捕获被迫捕获“foo/酒吧”。
解决方案是禁止该组织捕获任何不允许捕获的东西。
preg_match("{^/([^/]+)/$}", "/foo/bar/", $matches);
var_dump($matches); // match failed
关于PHP - 用于路由的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25734988/