Example #1
0
 /**
  * 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;
 }
Example #2
0
 /**
  * 执行模块
  * @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;
 }