5.0.0 - 严重 - 已关闭
使用url('index/News/list',['group_name'=>'aaa','page'=>1]);
时发现问题route.php 填写2下面2个路由
Route::rule('news/<group_name>/p-<page>', 'index/News/list');
Route::rule('news/<group_name>', 'index/News/list');
当参数只传group_name的时候,匹配后的路由为:www.test.com/aaa/p-<page>,原应该是:www.test.com/aaa
如果上面路由顺序颠倒下,传2个参数的时候,生成的路由为:
www.test.com/aaa/page/1,原应该是:www.test.com/aaa/p-1
后来检查代码,是路由解析代码有bug;
代码地址 thinkphp/library/think/Url.php:349
// 匹配路由地址
public function getRuleUrl($rule, &$vars = [], $allowDomain = '')
{
foreach ($rule as $item) {
list($url, $pattern, $domain, $suffix, $method) = $item;
if (is_string($allowDomain) && $domain != $allowDomain) {
continue;
}
if (!in_array($this->app['request']->port(), [80, 443])) {
$domain .= ':' . $this->app['request']->port();
}
if (empty($pattern)) {
return [rtrim($url, '?/-'), $domain, $suffix];
}
$type = $this->config['url_common_param'];
foreach ($pattern as $key => $val) {
if (isset($vars[$key])) {
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key, '<' . $key . '>'], $type ? $vars[$key] : urlencode($vars[$key]), $url);
unset($vars[$key]);//原值被unset,外部foreach拿不到原值
$url = str_replace(['/?', '-?'], ['/', '-'], $url);
$result = [rtrim($url, '?/-'), $domain, $suffix];
} elseif (2 == $val) {
$url = str_replace(['/[:' . $key . ']', '[:' . $key . ']', '<' . $key . '?>'], '', $url);
$url = str_replace(['/?', '-?'], ['/', '-'], $url);
$result = [rtrim($url, '?/-'), $domain, $suffix];
} else {
//未清空$result
break;
}
}
if (isset($result)) {
return $result;
}
}
return false;
}
问题处在内循环的foreach,问题一:第一个变量匹配成功后,第二个变量匹配失败,在最后的break;之前没有清空$result,出了内循环后会被return,
问题二:$vars在内循环第一个参数被匹配到后参数时被清除,第二参数匹配失败,到外循环foreach时,参数$vars拿不到原始的参数,在之前的内循环中被unset()了