diff --git a/library/think/App.php b/library/think/App.php index 2e50a40f..ca6e4536 100644 --- a/library/think/App.php +++ b/library/think/App.php @@ -280,7 +280,10 @@ class App if ($bind) { // 绑定模块 list($bindModule) = explode('/', $bind); - if ($module == $bindModule) { + if (empty($result[0])) { + $module = $bindModule; + $available = true; + } elseif ($module == $bindModule) { $available = true; } } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) { diff --git a/library/think/Route.php b/library/think/Route.php index 779e40fb..5958390a 100644 --- a/library/think/Route.php +++ b/library/think/Route.php @@ -63,6 +63,8 @@ class Route private static $group = []; // 路由命名标识(用于快速URL生成) private static $name = []; + // 当前子域名绑定 + private static $domain; /** * 注册变量规则 @@ -85,14 +87,18 @@ class Route * @access public * @param string|array $domain 子域名 * @param mixed $rule 路由规则 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ - public static function domain($domain = null, $rule = '') + public static function domain($domain, $rule = '', $option = [], $pattern = []) { if (is_array($domain)) { - self::$rules['domain'] = array_merge(self::$rules['domain'], $domain); + foreach ($domain as $key => $item) { + self::$rules['domain'][$key][] = is_array($item) ? $item : [$item, $option, $pattern]; + } } else { - self::$rules['domain'][$domain] = $rule; + self::$rules['domain'][$domain][] = [$rule, $option, $pattern]; } } @@ -100,7 +106,7 @@ class Route * 设置路由绑定 * @access public * @param mixed $bind 绑定信息 - * @param string $type 绑定类型 默认为module + * @param string $type 绑定类型 默认为module 支持 namespace class * @return mixed */ public static function bind($bind, $type = 'module') @@ -167,8 +173,13 @@ class Route unset($rule['__rest__']); } - $type = strtoupper($type); - foreach ($rule as $key => $val) { + self::registerRules($rule, strtoupper($type)); + } + + // 批量注册路由 + protected static function registerRules($rules, $type = '*') + { + foreach ($rules as $key => $val) { if (is_numeric($key)) { $key = array_shift($val); } @@ -358,7 +369,7 @@ class Route foreach (['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as $method) { if (!isset(self::$rules[$method][$name])) { self::$rules[$method][$name] = true; - } else { + } elseif (is_array(self::$rules[$method][$name])) { self::$rules[$method][$name] = array_merge(self::$rules['*'][$name], self::$rules[$method][$name]); } } @@ -610,9 +621,10 @@ class Route * 检测子域名部署 * @access public * @param Request $request Request请求对象 + * @param string $method 请求类型 * @return void */ - public static function checkDomain($request) + public static function checkDomain($request, $method) { // 域名规则 $rules = self::$rules['domain']; @@ -621,7 +633,7 @@ class Route $host = $request->host(); if (isset($rules[$host])) { // 完整域名或者IP配置 - $rule = $rules[$host]; + $item = $rules[$host]; } else { $rootDomain = Config::get('url_domain_root'); if ($rootDomain) { @@ -642,58 +654,68 @@ class Route } if ($subDomain && isset($rules[$subDomain])) { // 子域名配置 - $rule = $rules[$subDomain]; + $item = $rules[$subDomain]; } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { // 泛三级域名 - $rule = $rules['*.' . $domain2]; + $item = $rules['*.' . $domain2]; $panDomain = $domain3; } elseif (isset($rules['*']) && !empty($domain2)) { // 泛二级域名 if ('www' != $domain2) { - $rule = $rules['*']; + $item = $rules['*']; $panDomain = $domain2; } } } } - if (!empty($rule)) { - // 子域名部署规则 - if ($rule instanceof \Closure) { - // 执行闭包 - $reflect = new \ReflectionFunction($rule); - self::$bind = $reflect->invokeArgs([]); - return; - } - - if (strpos($rule, '?')) { - // 传入其它参数 - $array = parse_url($rule); - $result = $array['path']; - parse_str($array['query'], $params); - if (isset($panDomain)) { - $pos = array_search('*', $params); - if (false !== $pos) { - // 泛域名作为参数 - $params[$pos] = $panDomain; - } + if (!empty($item)) { + self::$domain = true; + foreach ($item as $val) { + list($rule, $option, $pattern) = $val; + // 子域名部署规则 + if ($rule instanceof \Closure) { + // 执行闭包 + $reflect = new \ReflectionFunction($rule); + self::$bind = $reflect->invokeArgs([]); + return; + } elseif (is_array($rule)) { + // 清空当前路由规则 + self::$rules[$method] = []; + self::$rules['*'] = []; + self::group('', function () use ($rule) { + // 动态注册域名的路由规则 + self::registerRules($rule); + }, $option, $pattern); + return; } - $_GET = array_merge($_GET, $params); - } else { - $result = $rule; - } - if (0 === strpos($result, '\\')) { - // 绑定到命名空间 例如 \app\index\behavior - self::$bind = ['type' => 'namespace', 'namespace' => $result, 'domain' => true]; - } elseif (0 === strpos($result, '@')) { - // 绑定到类 例如 @app\index\controller\User - self::$bind = ['type' => 'class', 'class' => substr($result, 1), 'domain' => true]; - } elseif (0 === strpos($result, '[')) { - // 绑定到分组 例如 [user] - self::$bind = ['type' => 'group', 'group' => substr($result, 1, -1), 'domain' => true]; - } else { - // 绑定到模块/控制器 例如 index/user - self::$bind = ['type' => 'module', 'module' => $result, 'domain' => true]; + if (strpos($rule, '?')) { + // 传入其它参数 + $array = parse_url($rule); + $result = $array['path']; + parse_str($array['query'], $params); + if (isset($panDomain)) { + $pos = array_search('*', $params); + if (false !== $pos) { + // 泛域名作为参数 + $params[$pos] = $panDomain; + } + } + $_GET = array_merge($_GET, $params); + } else { + $result = $rule; + } + + if (0 === strpos($result, '\\')) { + // 绑定到命名空间 例如 \app\index\behavior + self::$bind = ['type' => 'namespace', 'namespace' => $result]; + } elseif (0 === strpos($result, '@')) { + // 绑定到类 例如 @app\index\controller\User + self::$bind = ['type' => 'class', 'class' => substr($result, 1)]; + } else { + // 绑定到模块/控制器 例如 index/user + self::$bind = ['type' => 'module', 'module' => $result]; + } } } } @@ -722,13 +744,13 @@ class Route return $result; } } - + $method = $request->method(); // 检测域名部署 if ($checkDomain) { - self::checkDomain($request); + self::checkDomain($request, $method); } // 获取当前请求类型的路由规则 - $rules = self::$rules[$request->method()]; + $rules = self::$rules[$method]; // 检测URL绑定 $return = self::checkUrlBind($url, $rules, $depr); @@ -866,32 +888,23 @@ class Route */ private static function checkUrlBind(&$url, &$rules, $depr = '/') { - if (!empty(self::$bind['type'])) { + if (!empty(self::$bind)) { + $type = self::$bind['type']; + $bind = self::$bind[$type]; // 记录绑定信息 - App::$debug && Log::record('[ BIND ] ' . var_export(self::$bind, true), 'info'); + App::$debug && Log::record('[ BIND ] ' . var_export($bind, true), 'info'); // 如果有URL绑定 则进行绑定检测 - switch (self::$bind['type']) { + switch ($type) { case 'class': // 绑定到类 - return self::bindToClass($url, self::$bind['class'], $depr); + return self::bindToClass($url, $bind, $depr); case 'namespace': // 绑定到命名空间 - return self::bindToNamespace($url, self::$bind['namespace'], $depr); + return self::bindToNamespace($url, $bind, $depr); case 'module': // 如果有模块/控制器绑定 针对路由到 模块/控制器 有效 - $url = (empty(self::$bind['domain']) ? self::$bind['module'] . '/' : '') . ltrim($url, '/'); + $url = (empty(self::$domain) ? $bind . '/' : '') . ltrim($url, '/'); break; - case 'group': - // 绑定到路由分组 - $key = self::$bind['group']; - if (array_key_exists($key, $rules)) { - $item = $rules[self::$bind['group']]; - if (!empty(self::$bind['domain']) && true === $item) { - $rules = [self::$rules['*'][$key]]; - } else { - $rules = [$key => $item]; - } - } } } return false; @@ -1049,7 +1062,7 @@ class Route { if (isset(self::$bind['module'])) { // 如果有模块/控制器绑定 - $url = self::$bind['module'] . '/' . $url; + $url = self::$bind['module'] . '/' . ltrim($url, '/'); } list($path, $var) = self::parseUrlPath($url, $depr);