/** * URL生成 支持路由反射 * @param string $url URL表达式, * 格式:'[模块/控制器/操作]?参数1=值1&参数2=值2...@域名' * @控制器/操作?参数1=值1&参数2=值2... * \\命名空间类\\方法?参数1=值1&参数2=值2... * @param string|array $vars 传入的参数,支持数组和字符串 * @param string|bool $suffix 伪静态后缀,默认为true表示获取配置值 * @param boolean|string $domain 是否显示域名 或者直接传入域名 * @return string */ public static function build($url = '', $vars = '', $suffix = true, $domain = false) { if (false === $domain && Config::get('url_domain_deploy')) { $domain = true; } // 解析URL $info = parse_url($url); $url = !empty($info['path']) ? $info['path'] : ''; if (isset($info['fragment'])) { // 解析锚点 $anchor = $info['fragment']; if (false !== strpos($anchor, '?')) { // 解析参数 list($anchor, $info['query']) = explode('?', $anchor, 2); } if (false !== strpos($anchor, '@')) { // 解析域名 list($anchor, $domain) = explode('@', $anchor, 2); } } elseif (strpos($url, '@')) { // 解析域名 list($url, $domain) = explode('@', $url, 2); } // 解析参数 if (is_string($vars)) { // aaa=1&bbb=2 转换成数组 parse_str($vars, $vars); } if (isset($info['query'])) { // 解析地址里面参数 合并到vars parse_str($info['query'], $params); $vars = array_merge($params, $vars); } // 获取路由别名 $alias = self::getRouteAlias(); // 检测路由 if (0 !== strpos($url, '/') && isset($alias[$url]) && ($match = self::getRouteUrl($alias[$url], $vars))) { // 处理路由规则中的特殊字符 $url = str_replace('[--think--]', '', $match); } else { // 路由不存在 直接解析 $url = self::parseUrl($url); } // 检测URL绑定 $type = Route::getBind('type'); if ($type) { $bind = Route::getBind($type); if (0 === strpos($url, $bind)) { $url = substr($url, strlen($bind) + 1); } } // 还原URL分隔符 $depr = Config::get('pathinfo_depr'); $url = str_replace('/', $depr, $url); // URL后缀 $suffix = in_array($url, ['/', '']) ? '' : self::parseSuffix($suffix); // 锚点 $anchor = !empty($anchor) ? '#' . $anchor : ''; // 参数组装 if (!empty($vars)) { // 添加参数 if (Config::get('url_common_param')) { $vars = urldecode(http_build_query($vars)); $url .= $suffix . '?' . $vars . $anchor; } else { foreach ($vars as $var => $val) { if ('' !== trim($val)) { $url .= $depr . $var . $depr . urlencode($val); } } $url .= $suffix . $anchor; } } else { $url .= $suffix . $anchor; } // 检测域名 $domain = self::parseDomain($url, $domain); // URL组装 $url = $domain . (self::$root ?: Request::instance()->root()) . '/' . ltrim($url, '/'); return $url; }
/** * 执行模块 * @access public * @param array $result 模块/控制器/操作 * @param array $config 配置参数 * @param bool $convert 是否自动转换控制器和操作名 * @return mixed */ public static function module($result, $config, $convert = null) { if (is_string($result)) { $result = explode('/', $result); } $request = Request::instance(); if ($config['app_multi_module']) { // 多模块部署 $module = ucfirst(strip_tags(strtolower($result[0] ?: $config['default_module']))); $bind = Route::getBind('module'); $available = false; if ($bind) { // 绑定模块 list($bindModule) = explode('/', $bind); if ($module == $bindModule) { $available = true; } } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . '/' . $module)) { $available = true; } // 模块初始化 if ($module && $available) { // 初始化模块 $request->module($module); $config = self::init($module); } else { throw new \Norma\Exception\HttpException(404, 'module not exists:' . $module); } } else { // 单一模块部署 $module = ''; $request->module($module); } // 当前模块路径 App::$modulePath = APP_PATH . '/' . ($module ? $module . DIRECTORY_SEPARATOR : ''); // 是否自动转换控制器和操作名 $convert = is_bool($convert) ? $convert : $config['url_convert']; // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); $controller = ucfirst($convert ? strtolower($controller) : $controller); // 获取操作名 $actionName = strip_tags($result[2] ?: $config['default_action']); $actionName = $convert ? strtolower($actionName) : $actionName; // 设置当前请求的控制器、操作 $request->controller($controller)->action($actionName); // 监听module_init //Hook::listen('module_init', $request); try { $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); if (is_null($instance)) { throw new \Norma\Exception\HttpException(404, 'controller not exists:' . $controller); } // 获取当前操作名 $action = $actionName . $config['action_suffix']; if (!preg_match('/^[A-Za-z](\\w)*$/', $action)) { // 非法操作 throw new \ReflectionException('illegal action name:' . $actionName); } // 执行操作方法 $call = [$instance, $action]; //Hook::listen('action_begin', $call); $data = self::invokeMethod($call); } catch (\ReflectionException $e) { // 操作不存在 if (method_exists($instance, '_empty')) { $method = new \ReflectionMethod($instance, '_empty'); $data = $method->invokeArgs($instance, [$action, '']); self::$debug && Log::record('[ RUN ] ' . $method->__toString(), 'info'); } else { throw new \Norma\Exception\HttpException(404, 'method not exists:' . (new \ReflectionClass($instance))->getName() . '->' . $action); } } return $data; }