优化路由检测 取消路由映射 映射定义并入路由规则统一定义 配合调整Url类

This commit is contained in:
thinkphp
2016-07-08 16:03:20 +08:00
parent 09cac83137
commit 10dd770c39
2 changed files with 197 additions and 235 deletions

View File

@@ -29,6 +29,10 @@ class Route
'HEAD' => [],
'OPTIONS' => [],
'*' => [],
'map' => [],
'alias' => [],
'domain' => [],
'pattern' => [],
];
// REST路由操作方法定义
@@ -50,75 +54,44 @@ class Route
'DELETE' => 'delete',
];
// URL映射规则
private static $map = [];
// 子域名部署规则
private static $domain = [];
// 子域名
private static $subDomain = '';
// 变量规则
private static $pattern = [];
// 域名绑定
private static $bind = [];
// 当前分组
private static $group;
// 当前参数
private static $option = [];
// 路由别名
private static $alias = [];
/**
* 注册或者获取URL映射规则
* @access public
* @param string|array $map 映射名
* @param string $route 路由地址
* @return mixed
*/
public static function map($map = '', $route = '')
{
return self::setting('map', $map, $route);
}
/**
* 注册或者获取变量规则
* 注册变量规则
* @access public
* @param string|array $name 变量名
* @param string $rule 变量规则
* @return mixed
* @return void
*/
public static function pattern($name = '', $rule = '')
public static function pattern($name = null, $rule = '')
{
return self::setting('pattern', $name, $rule);
if (is_array($name)) {
self::$rules['pattern'] = array_merge(self::$rules['pattern'], $name);
} else {
self::$rules['pattern'][$name] = $rule;
}
}
/**
* 注册或者获取子域名部署规则
* 注册子域名部署规则
* @access public
* @param string|array $domain 子域名
* @param mixed $rule 路由规则
* @return mixed
* @return void
*/
public static function domain($domain = '', $rule = '')
public static function domain($domain = null, $rule = '')
{
return self::setting('domain', $domain, $rule);
}
/**
* 设置属性
* @access public
* @param string $var 属性名称
* @param string|array $name 变量名称
* @param mixed $value 变量值
* @return mixed
*/
private static function setting($var, $name = '', $value = '')
{
if (is_array($name)) {
self::${$var} = self::${$var}+$name;
} elseif (empty($value)) {
return empty($name) ? self::${$var} : self::${$var}[$name];
if (is_array($domain)) {
self::$rules['domain'] = array_merge(self::$rules['domain'], $domain);
} else {
self::${$var}[$name] = $value;
self::$rules['domain'][$domain] = $rule;
}
}
@@ -156,25 +129,19 @@ class Route
{
// 检查域名部署
if (isset($rule['__domain__'])) {
self::domain($rule['__domain__']);
self::$rules['domain'] = $rule['__domain__'];
unset($rule['__domain__']);
}
// 检查变量规则
if (isset($rule['__pattern__'])) {
self::pattern($rule['__pattern__']);
self::$rules['pattern'] = $rule['__pattern__'];
unset($rule['__pattern__']);
}
// 检查路由映射
if (isset($rule['__map__'])) {
self::map($rule['__map__']);
unset($rule['__map__']);
}
// 检查路由别名
if (isset($rule['__alias__'])) {
self::alias($rule['__alias__']);
self::$rules['alias'] = $rule['__alias__'];
unset($rule['__alias__']);
}
@@ -511,12 +478,10 @@ class Route
*/
public static function alias($rule = null, $route = '', $option = [])
{
if (is_null($rule)) {
return self::$alias;
} elseif (is_array($rule)) {
self::$alias = array_merge(self::$alias, $rule);
if (is_array($rule)) {
self::$rules['alias'] = array_merge(self::$rules['alias'], $rule);
} else {
self::$alias[$rule] = $option ? [$route, $option] : $route;
self::$rules['alias'][$rule] = $option ? [$route, $option] : $route;
}
}
@@ -566,14 +531,22 @@ class Route
}
/**
* 获取路由定义
* 获取或者批量设置路由定义
* @access public
* @param string $method 请求类型
* @param mixed $rules 请求类型或者路由定义数组
* @return array
*/
public static function getRules($method = '')
public static function rules($rules = '')
{
return $method ? self::$rules[$method] : self::$rules;
if (is_array($rules)) {
self::$rules = $rules;
} elseif ($rules) {
return self::$rules[$rules];
} else {
$rules = self::$rules;
unset($rules['pattern'], $rules['alias'], $rules['domain']);
return $rules;
}
}
/**
@@ -585,7 +558,7 @@ class Route
public static function checkDomain($request)
{
// 域名规则
$rules = self::$domain;
$rules = self::$rules['domain'];
// 开启子域名部署 支持二级和三级域名
if (!empty($rules)) {
$host = $request->host();
@@ -685,133 +658,155 @@ class Route
$url = str_replace($depr, '/', $url);
}
if (isset(self::$map[$url])) {
// URL映射完整静态URL匹配
return self::parseModule(self::$map[$url], $depr);
}
if (strpos($url, '/') && isset(self::$alias[strstr($url, '/', true)])) {
// 路由别名
$array = explode('/', $url, 2);
$item = self::$alias[$array[0]];
if (is_array($item)) {
list($rule, $option) = $item;
} else {
$rule = $item;
}
// 参数有效性检查
if (isset($option) && !self::checkOption($option, $url, $request)) {
// 路由不匹配
} elseif (0 === strpos($rule, '\\')) {
// 路由到类
return self::bindToClass($array[1], substr($rule, 1), $depr);
} elseif (0 === strpos($url, '@')) {
// 路由到控制器类
return self::bindToController($array[1], substr($rule, 1), $depr);
} else {
// 路由到模块/控制器
return self::bindToModule($array[1], $rule, $depr);
if (strpos($url, '/') && isset(self::$rules['alias'][strstr($url, '/', true)])) {
// 检测路由别名
$result = self::checkRouteAlias($request, $url, $depr);
if (false !== $result) {
return $result;
}
}
// 获取当前请求类型的路由规则
$rules = self::$rules[$request->method()];
// 检测域名部署
if ($checkDomain) {
self::checkDomain($request);
}
// 检测URL绑定
$return = self::checkUrlBind($url, $rules, $depr);
if ($return) {
if (false !== $return) {
return $return;
}
// 获取当前请求类型的路由规则
$rules = self::$rules[$request->method()];
if (isset($rules[$url])) {
// 静态路由规则检测
$rule = $rules[$url];
if (true === $rule) {
$rule = self::$rules['*'][$url];
}
if (!empty($rule['option']['complete_match'])) {
// 是否完整匹配
return self::parseRule($url, $rule['route'], $url);
} else {
return self::checkRule($url, $rule['route'], $url, [], $rule['option']);
}
}
// 路由规则检测
if (!empty($rules)) {
foreach ($rules as $rule => $val) {
if (true === $val) {
$val = self::$rules['*'][$rule];
}
$route = $val['route'];
$vars = $val['var'];
$option = $val['option'];
$pattern = $val['pattern'];
// 参数有效性检查
if (!self::checkOption($option, $url, $request)) {
continue;
}
if ('__miss__' == $rule) {
// 指定分组MISS路由
$miss = $route;
continue;
}
if (is_array($val['rule'])) {
// 分组路由
if (($pos = strpos($rule, ':')) || ($pos = strpos($rule, '<'))) {
$str = substr($rule, 0, $pos);
} else {
$str = $rule;
}
if (0 !== strpos($url, $str)) {
continue;
}
$missGroup = false;
// 匹配到路由分组
foreach ($val['rule'] as $item) {
$key = $item['rule'];
$route = $item['route'];
$vars = $item['var'];
$option = $item['option'];
$pattern = $item['pattern'];
// 检查参数有效性
if (!self::checkOption($option, $url, $request)) {
continue;
}
if ('__miss__' == $key) {
// 指定分组MISS路由
$missGroup = $item;
continue;
}
$key = $rule . '/' . ltrim($key, '/');
$result = self::checkRule($key, $route, $url, $pattern, $option);
if (false !== $result) {
$request->routeInfo(['rule' => $key, 'route' => $route, 'pattern' => $pattern, 'option' => $option]);
return $result;
}
}
if ($missGroup) {
// 未匹配所有路由的路由规则处理
return self::parseRule('', $missGroup, $url, []);
}
} else {
// 规则路由
$result = self::checkRule($rule, $route, $url, $pattern, $option);
if (false !== $result) {
$request->routeInfo(['rule' => $rule, 'route' => $route, 'pattern' => $pattern, 'option' => $option]);
return $result;
}
}
}
if (isset($miss)) {
// 未匹配所有路由的路由规则处理
return self::parseRule('', $miss, $url, []);
}
return self::checkRoute($request, $rules, $url);
}
return false;
}
/**
* 检测路由规则
* @access private
* @param Request $request
* @param array $rules 路由规则
* @param string $url URL地址
* @param string $group 路由分组名
* @return mixed
*/
private static function checkRoute($request, $rules, $url, $group = '')
{
// 匹配到路由分组
foreach ($rules as $key => $item) {
if (true === $item) {
$item = self::$rules['*'][$key];
}
$rule = $item['rule'];
$route = $item['route'];
$vars = $item['var'];
$option = $item['option'];
$pattern = $item['pattern'];
// 检查参数有效性
if (!self::checkOption($option, $url, $request)) {
continue;
}
if ('__miss__' == $rule) {
// 指定分组MISS路由
$miss = $item;
continue;
}
if (is_array($rule)) {
// 分组路由
if (($pos = strpos($key, ':')) || ($pos = strpos($key, '<'))) {
$str = substr($key, 0, $pos);
} else {
$str = $key;
}
if (0 !== strpos($url, $str)) {
continue;
}
$result = self::checkRoute($request, $rule, $url, $key);
if (false !== $result) {
return $result;
}
} else {
if ($group) {
$rule = $group . '/' . ltrim($rule, '/');
}
$result = self::checkRule($rule, $route, $url, $pattern, $option);
if (false !== $result) {
$request->routeInfo(['rule' => $rule, 'route' => $route, 'pattern' => $pattern, 'option' => $option, 'var' => $request->route()]);
return $result;
}
}
}
if (isset($miss)) {
// 未匹配所有路由的路由规则处理
return self::parseRule('', $miss, $url);
}
return false;
}
/**
* 检测路由别名
* @access private
* @param Request $request
* @param string $url URL地址
* @param string $depr URL分隔符
* @return mixed
*/
private static function checkRouteAlias($request, $url, $depr)
{
$array = explode('/', $url, 2);
$item = self::$rules['alias'][$array[0]];
if (is_array($item)) {
list($rule, $option) = $item;
} else {
$rule = $item;
}
// 参数有效性检查
if (isset($option) && !self::checkOption($option, $url, $request)) {
// 路由不匹配
return false;
} elseif (0 === strpos($rule, '\\')) {
// 路由到类
return self::bindToClass($array[1], substr($rule, 1), $depr);
} elseif (0 === strpos($url, '@')) {
// 路由到控制器类
return self::bindToController($array[1], substr($rule, 1), $depr);
} else {
// 路由到模块/控制器
return self::bindToModule($array[1], $rule, $depr);
}
}
/**
* 检测URL绑定
* @access private
* @param string $url URL地址
* @param array $rules 路由规则
* @param string $depr URL分隔符
* @return false
* @return mixed
*/
private static function checkUrlBind(&$url, &$rules, $depr = '/')
{
@@ -878,27 +873,6 @@ class Route
return ['type' => 'method', 'method' => [$namespace . '\\' . $class, $method], 'params' => []];
}
/**
* 绑定到应用 直接进行控制器类库访问
* @access public
* @param string $url URL地址
* @param string $depr URL分隔符
* @return array
*/
public static function bindToApp($url, $depr = '/')
{
$array = explode($depr, $url, 4);
$module = !empty($array[0]) ? $array[0] : Config::get('default_module');
$controller = !empty($array[1]) ? $array[1] : Config::get('default_controller');
$method = !empty($array[2]) ? $array[2] : Config::get('default_action');
$layer = Config::get('url_controller_layer');
$class = App::$namespace . '\\' . $module . '\\' . $layer . '\\' . $controller;
if (!empty($array[3])) {
self::parseUrlParams($array[3]);
}
return ['type' => 'method', 'method' => [$class, $method], 'params' => []];
}
/**
* 绑定到控制器类
* @access public
@@ -992,7 +966,7 @@ class Route
return false;
}
}
$pattern = array_merge(self::$pattern, $pattern);
$pattern = array_merge(self::$rules['pattern'], $pattern);
if (false !== $match = self::match($url, $rule, $pattern, $merge)) {
// 匹配到路由规则
// 检测是否定义路由
@@ -1169,7 +1143,7 @@ class Route
* @param bool $merge 合并额外变量
* @return array
*/
private static function parseRule($rule, $route, $pathinfo, $matches, $merge = false)
private static function parseRule($rule, $route, $pathinfo, $matches = [], $merge = false)
{
// 解析路由规则
if ($rule) {
@@ -1195,7 +1169,7 @@ class Route
// 获取路由地址规则
$url = is_array($route) ? $route[0] : $route;
// 替换路由地址中的变量
if (is_string($url)) {
if (is_string($url) && !empty($matches)) {
foreach ($matches as $key => $val) {
if (false !== strpos($url, ':' . $key)) {
$url = str_replace(':' . $key, $val, $url);

View File

@@ -155,45 +155,44 @@ class Url
// 检测域名
protected static function parseDomain(&$url, $domain)
{
if ($domain) {
$request = Request::instance();
if (true === $domain) {
// 自动判断域名
$domain = $request->host();
if (Config::get('url_domain_deploy')) {
// 根域名
$urlDomainRoot = Config::get('url_domain_root');
$domains = Route::domain();
$route_domain = array_keys($domains);
foreach ($route_domain as $domain_prefix) {
if (0 === strpos($domain_prefix, '*.') && strpos($domain, ltrim($domain_prefix, '*.')) !== false) {
foreach ($domains as $key => $rule) {
$rule = is_array($rule) ? $rule[0] : $rule;
if (false === strpos($key, '*') && 0 === strpos($url, $rule)) {
$url = ltrim($url, $rule);
$domain = $key;
// 生成对应子域名
if (!empty($urlDomainRoot)) {
$domain .= $urlDomainRoot;
}
break;
} else if (false !== strpos($key, '*')) {
if (!empty($urlDomainRoot)) {
$domain .= $urlDomainRoot;
}
break;
if (!$domain) {
return '';
}
$request = Request::instance();
if (true === $domain) {
// 自动判断域名
$domain = $request->host();
if (Config::get('url_domain_deploy')) {
// 根域名
$urlDomainRoot = Config::get('url_domain_root');
$domains = Route::rules('domain');
$route_domain = array_keys($domains);
foreach ($route_domain as $domain_prefix) {
if (0 === strpos($domain_prefix, '*.') && strpos($domain, ltrim($domain_prefix, '*.')) !== false) {
foreach ($domains as $key => $rule) {
$rule = is_array($rule) ? $rule[0] : $rule;
if (false === strpos($key, '*') && 0 === strpos($url, $rule)) {
$url = ltrim($url, $rule);
$domain = $key;
// 生成对应子域名
if (!empty($urlDomainRoot)) {
$domain .= $urlDomainRoot;
}
break;
} else if (false !== strpos($key, '*')) {
if (!empty($urlDomainRoot)) {
$domain .= $urlDomainRoot;
}
break;
}
}
}
}
} else {
$domain .= strpos($domain, '.') ? '' : strstr($request->host(), '.');
}
$domain = ($request->isSsl() ? 'https://' : 'http://') . $domain;
} else {
$domain = '';
$domain .= strpos($domain, '.') ? '' : strstr($request->host(), '.');
}
$domain = ($request->isSsl() ? 'https://' : 'http://') . $domain;
return $domain;
}
@@ -265,7 +264,7 @@ class Url
return $item;
}
// 获取路由定义
$array = Route::getRules();
$array = Route::rules();
foreach ($array as $type => $rules) {
foreach ($rules as $rule => $val) {
if (true === $val || empty($val['rule'])) {
@@ -305,19 +304,8 @@ class Url
}
}
// 检测路由映射
$maps = Route::map();
foreach ($maps as $rule => $route) {
$param = [];
if (strpos($route, '?')) {
list($route, $str) = explode('?', $route, 2);
parse_str($str, $param);
}
$item[$route][] = [$rule, [], $param];
}
// 检测路由别名
$alias = Route::alias();
$alias = Route::rules('alias');
foreach ($alias as $rule => $route) {
$route = is_array($route) ? $route[0] : $route;
$item[$route][] = [$rule, [], []];