取消正则路由定义 修正可选参数定义变量规则的一个BUG 增加url_params_depr参数用于配置URL参数分隔符

This commit is contained in:
thinkphp
2016-01-07 23:00:20 +08:00
parent 861570edfe
commit 5f40a706ab
2 changed files with 42 additions and 132 deletions

View File

@@ -101,13 +101,9 @@ class App
// 执行类,例如行为 // 执行类,例如行为
$data = Hook::exec(self::$dispatch['class'], self::$dispatch['method'], self::$dispatch['params']); $data = Hook::exec(self::$dispatch['class'], self::$dispatch['method'], self::$dispatch['params']);
break; break;
case 'regex_closure': case 'closure':
// 正则闭包
$data = self::invokeRegex(self::$dispatch['closure'], self::$dispatch['params']);
break;
case 'rule_closure':
// 规则闭包 // 规则闭包
$data = self::invokeRule(self::$dispatch['closure'], self::$dispatch['params']); $data = self::invoke(self::$dispatch['closure'], self::$dispatch['params']);
break; break;
default: default:
throw new Exception('dispatch type not support', 10008); throw new Exception('dispatch type not support', 10008);
@@ -118,26 +114,8 @@ class App
return Response::send($data, Response::type(), Config::get('response_return')); return Response::send($data, Response::type(), Config::get('response_return'));
} }
// 执行正则匹配下的闭包方法 支持参数调用
private static function invokeRegex($closure, $var = [])
{
$reflect = new \ReflectionFunction($closure);
$params = $reflect->getParameters();
$args = [];
array_shift($var);
foreach ($params as $param) {
$name = $param->getName();
if (!empty($var)) {
$args[] = array_shift($var);
} elseif ($param->isDefaultValueAvailable()) {
$args[] = $param->getDefaultValue();
}
}
return $reflect->invokeArgs($args);
}
// 执行规则匹配下的闭包方法 支持参数调用 // 执行规则匹配下的闭包方法 支持参数调用
private static function invokeRule($closure, $var = []) private static function invoke($closure, $var = [])
{ {
$reflect = new \ReflectionFunction($closure); $reflect = new \ReflectionFunction($closure);
$params = $reflect->getParameters(); $params = $reflect->getParameters();

View File

@@ -331,29 +331,9 @@ class Route
foreach ($rules as $rule => $val) { foreach ($rules as $rule => $val) {
$option = $val['option']; $option = $val['option'];
$pattern = $val['pattern']; $pattern = $val['pattern'];
// 请求类型检测
if (isset($option['method']) && false === stripos($option['method'], REQUEST_METHOD)) {
continue;
}
// 伪静态后缀检测
if (isset($option['ext']) && __EXT__ != $option['ext']) {
continue;
}
// 域名检测
if (isset($option['domain']) && $_SERVER['HTTP_HOST'] != $option['domain']) {
continue;
}
// https检测
if (!empty($option['https']) && !self::isSsl()) {
continue;
}
// 自定义检测
if (!empty($option['callback']) && is_callable($option['callback']) && false === call_user_func($option['callback'])) {
continue;
}
// 行为检测 // 参数有效性检查
if (!empty($option['behavior']) && false === Hook::exec($option['behavior'])) { if (!self::checkOption($option)) {
continue; continue;
} }
@@ -368,32 +348,19 @@ class Route
$key = array_shift($route); $key = array_shift($route);
} }
$url1 = substr($url, strlen($rule) + 1); $url1 = substr($url, strlen($rule) + 1);
if (0 === strpos($key, '/') && preg_match($key, $url1, $matches)) { // 检查规则路由
// 检查正则路由 if (is_array($route)) {
return self::checkRegex($route, $url1, $matches); $option1 = $route[1];
} else { // 检查参数有效性
// 检查规则路由 if (!self::checkOption($option1)) {
if (is_array($route)) { continue;
$option1 = $route[1];
// 请求类型检测
if (isset($option1['method']) && false === stripos($option1['method'], REQUEST_METHOD)) {
continue;
}
// 伪静态后缀检测
if (isset($option1['ext']) && __EXT__ != $option1['ext']) {
continue;
}
// https检测
if (!empty($option1['https']) && !self::isSsl()) {
continue;
}
$pattern = array_merge($pattern, isset($route[2]) ? $route[2] : []);
$route = $route[0];
}
$result = self::checkRule($key, $route, $url1, $pattern);
if (false !== $result) {
return $result;
} }
$pattern = array_merge($pattern, isset($route[2]) ? $route[2] : []);
$route = $route[0];
}
$result = self::checkRule($key, $route, $url1, $pattern);
if (false !== $result) {
return $result;
} }
} }
} else { } else {
@@ -402,14 +369,10 @@ class Route
} }
// 单项路由 // 单项路由
$route = !empty($val['route']) ? $val['route'] : ''; $route = !empty($val['route']) ? $val['route'] : '';
if (0 === strpos($rule, '/') && preg_match($rule, $url, $matches)) { // 规则路由
return self::checkRegex($route, $url, $matches); $result = self::checkRule($rule, $route, $url, $pattern);
} else { if (false !== $result) {
// 规则路由 return $result;
$result = self::checkRule($rule, $route, $url, $pattern);
if (false !== $result) {
return $result;
}
} }
} }
} }
@@ -417,17 +380,20 @@ class Route
return false; return false;
} }
/** // 路由参数有效性检查
* 检查正则路由 private static function checkOption($option)
*/
private static function checkRegex($route, $url, $matches)
{ {
// 正则路由 // 请求类型检测
if ($route instanceof \Closure) { if ((isset($option['method']) && false === stripos($option['method'], REQUEST_METHOD))
// 执行闭包 || (isset($option['ext']) && __EXT__ != $option['ext']) // 伪静态后缀检测
return ['type' => 'regex_closure', 'closure' => $route, 'params' => $matches]; || (isset($option['domain']) && $_SERVER['HTTP_HOST'] != $option['domain']) // 域名检测
|| (!empty($option['https']) && !self::isSsl()) // https检测
|| (!empty($option['behavior']) && false === Hook::exec($option['behavior'])) // 行为检测
|| (!empty($option['callback']) && is_callable($option['callback']) && false === call_user_func($option['callback'])) // 自定义检测
) {
return false;
} }
return self::parseRegex($matches, $route, $url); return true;
} }
/** /**
@@ -435,6 +401,11 @@ class Route
*/ */
private static function checkRule($rule, $route, $url, $pattern) private static function checkRule($rule, $route, $url, $pattern)
{ {
// 检测是否设置了参数分隔符
if ($depr = Config::get('url_params_depr')) {
$url = str_replace($depr, '/', $url);
$rule = str_replace($depr, '/', $rule);
}
$len1 = substr_count($url, '/'); $len1 = substr_count($url, '/');
$len2 = substr_count($rule, '/'); $len2 = substr_count($rule, '/');
if ($len1 >= $len2 || strpos($rule, '[')) { if ($len1 >= $len2 || strpos($rule, '[')) {
@@ -450,7 +421,7 @@ class Route
if (false !== $match = self::match($url, $rule, $pattern)) { if (false !== $match = self::match($url, $rule, $pattern)) {
if ($route instanceof \Closure) { if ($route instanceof \Closure) {
// 执行闭包 // 执行闭包
return ['type' => 'rule_closure', 'closure' => $route, 'params' => $match]; return ['type' => 'closure', 'closure' => $route, 'params' => $match];
} }
return self::parseRule($rule, $route, $url); return self::parseRule($rule, $route, $url);
} }
@@ -540,7 +511,6 @@ class Route
$m1 = explode('/', $url); $m1 = explode('/', $url);
$m2 = explode('/', $rule); $m2 = explode('/', $rule);
$var = []; $var = [];
foreach ($m2 as $key => $val) { foreach ($m2 as $key => $val) {
if (0 === strpos($val, '[:')) { if (0 === strpos($val, '[:')) {
// 可选参数 // 可选参数
@@ -548,10 +518,6 @@ class Route
} }
if (0 === strpos($val, ':')) { if (0 === strpos($val, ':')) {
// URL变量 // URL变量
if ($pos = strpos($val, '|')) {
// 使用函数过滤
$val = substr($val, 1, $pos - 1);
}
if (strpos($val, '\\')) { if (strpos($val, '\\')) {
$type = substr($val, -1); $type = substr($val, -1);
if ('d' == $type && !is_numeric($m1[$key])) { if ('d' == $type && !is_numeric($m1[$key])) {
@@ -561,7 +527,7 @@ class Route
} else { } else {
$name = substr($val, 1); $name = substr($val, 1);
} }
if (isset($pattern[$name]) && !preg_match($pattern[$name], $m1[$key])) { if (isset($m1[$key]) && isset($pattern[$name]) && !preg_match($pattern[$name], $m1[$key])) {
// 检查变量规则 // 检查变量规则
return false; return false;
} }
@@ -590,21 +556,14 @@ class Route
$item = substr($item, 1, -1); $item = substr($item, 1, -1);
} }
if (0 === strpos($item, ':')) { if (0 === strpos($item, ':')) {
// 动态变量获取
if ($pos = strpos($item, '|')) {
// 支持函数过滤
$fun = substr($item, $pos + 1);
$item = substr($item, 0, $pos);
}
if (strpos($item, '\\')) { if (strpos($item, '\\')) {
$var = substr($item, 1, -2); $var = substr($item, 1, -2);
} else { } else {
$var = substr($item, 1); $var = substr($item, 1);
} }
$matches[$var] = array_shift($paths); $matches[$var] = array_shift($paths);
if (!empty($fun)) {
$matches[$var] = $fun($matches[$var]);
}
} else { } else {
// 过滤URL中的静态变量 // 过滤URL中的静态变量
array_shift($paths); array_shift($paths);
@@ -643,33 +602,6 @@ class Route
return $result; return $result;
} }
// 解析正则路由
private static function parseRegex($matches, $route, $pathinfo)
{
// 获取路由地址规则
$url = is_array($route) ? $route[0] : $route;
$url = preg_replace('/:(\d+)/e', '$matches[\\1]', $url);
if (0 === strpos($url, '/') || 0 === strpos($url, 'http')) {
// 路由重定向跳转
$result = ['type' => 'redirect', 'url' => $url, 'status' => (is_array($route) && isset($route[1])) ? $route[1] : 301];
} elseif (0 === strpos($url, '\\')) {
// 路由到类
$result = ['type' => 'class', 'class' => $url, 'method' => isset($route[1]) ? $route[1] : '', 'params' => $matches];
} elseif (0 === strpos($url, '@')) {
// 路由到控制器
$result = ['type' => 'controller', 'controller' => substr($url, 1), 'params' => $matches];
} else {
// 解析路由地址
$result = self::parseRoute($url);
$var = $result['var'];
// 解析剩余的URL参数
$regx = substr_replace($pathinfo, '', 0, strlen($matches[0]));
self::parseUrlParams($regx, $var);
$result = ['type' => 'module', 'data' => $result['route']];
}
return $result;
}
// 解析URL地址中的参数到$_GET // 解析URL地址中的参数到$_GET
private static function parseUrlParams($url, $var) private static function parseUrlParams($url, $var)
{ {