Example #1
0
File: app.php Project: xl602/think
 /**
  * URL调度
  * @access public
  *
  * @param $config
  *
  * @throws Exception
  */
 public static function dispatch($config)
 {
     if (isset($_GET[$config['var_pathinfo']])) {
         // 判断URL里面是否有兼容模式参数
         $_SERVER['PATH_INFO'] = $_GET[$config['var_pathinfo']];
         unset($_GET[$config['var_pathinfo']]);
     } elseif (IS_CLI) {
         // CLI模式下 index.php module/controller/action/params/...
         $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
     }
     // 检测域名部署
     if (!IS_CLI && !empty($config['url_domain_deploy'])) {
         if ($config['url_domain_rules']) {
             Route::domain($config['url_domain_rules']);
         }
         if ($match = Route::checkDomain()) {
             !defined('BIND_MODULE') && !empty($match[0]) && define('BIND_MODULE', $match[0]);
             !defined('BIND_CONTROLLER') && !empty($match[1]) && define('BIND_CONTROLLER', $match[1]);
             !defined('BIND_ACTION') && !empty($match[2]) && define('BIND_ACTION', $match[2]);
         }
     }
     // 监听path_info
     APP_HOOK && Hook::listen('path_info');
     // 分析PATHINFO信息
     if (!isset($_SERVER['PATH_INFO'])) {
         foreach ($config['pathinfo_fetch'] as $type) {
             if (!empty($_SERVER[$type])) {
                 $_SERVER['PATH_INFO'] = 0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME']) ? substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
                 break;
             }
         }
     }
     // [模块,控制器,操作]
     $result = [null, null, null];
     if (empty($_SERVER['PATH_INFO'])) {
         $_SERVER['PATH_INFO'] = '';
         define('__INFO__', '');
         define('__EXT__', '');
     } else {
         $_SERVER['PATH_INFO'] = trim($_SERVER['PATH_INFO'], '/');
         define('__INFO__', $_SERVER['PATH_INFO']);
         // URL后缀
         define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION)));
         if (__INFO__) {
             if ($config['url_deny_suffix'] && preg_match('/\\.(' . $config['url_deny_suffix'] . ')$/i', __INFO__)) {
                 throw new Exception('url suffix deny');
             }
             // 去除URL后缀
             $_SERVER['PATH_INFO'] = preg_replace($config['url_html_suffix'] ? '/\\.(' . trim($config['url_html_suffix'], '.') . ')$/i' : '/\\.' . __EXT__ . '$/i', '', __INFO__);
             $depr = $config['pathinfo_depr'];
             // 还原劫持后真实pathinfo
             $path_info = (defined('BIND_MODULE') ? BIND_MODULE . $depr : '') . (defined('BIND_CONTROLLER') ? BIND_CONTROLLER . $depr : '') . (defined('BIND_ACTION') ? BIND_ACTION . $depr : '') . $_SERVER['PATH_INFO'];
             // 路由检测
             if (!empty($config['url_route_on'])) {
                 // 开启路由 则检测路由配置
                 Route::register(!empty($config['route']) ? $config['route'] : null);
                 $result = Route::check($path_info, $depr);
                 if (false === $result) {
                     // 路由无效
                     if ($config['url_route_must']) {
                         throw new Exception('route not define ');
                     } else {
                         // 继续分析URL
                         $result = Route::parseUrl($path_info, $depr);
                     }
                 }
             } else {
                 // 分析URL地址
                 $result = Route::parseUrl($path_info, $depr);
             }
         }
     }
     if (APP_MULTI_MODULE) {
         $module = strtolower($result[0] ?: $config['default_module']);
         if ($maps = $config['url_module_map']) {
             if (isset($maps[$module])) {
                 // 记录当前别名
                 define('MODULE_ALIAS', $module);
                 // 获取实际的项目名
                 $module = $maps[MODULE_ALIAS];
             } elseif (array_search($module, $maps)) {
                 // 禁止访问原始项目
                 $module = '';
             }
         }
         // 获取模块名称
         define('MODULE_NAME', defined('BIND_MODULE') ? BIND_MODULE : strip_tags($module));
         // 模块初始化
         if (MODULE_NAME && !in_array(MODULE_NAME, $config['deny_module_list']) && is_dir(APP_PATH . MODULE_NAME)) {
             APP_HOOK && Hook::listen('app_begin');
             define('MODULE_PATH', APP_PATH . MODULE_NAME . DS);
             define('VIEW_PATH', MODULE_PATH . VIEW_LAYER . DS);
             // 初始化模块
             self::initModule(MODULE_NAME, $config);
         } else {
             throw new Exception('module [ ' . MODULE_NAME . ' ] not exists ', 10005);
         }
     } else {
         define('MODULE_NAME', '');
         define('MODULE_PATH', APP_PATH);
         define('VIEW_PATH', MODULE_PATH . VIEW_LAYER . DS);
     }
     // 获取控制器名
     $controller = strip_tags(strtolower($result[1] ?: Config::get('default_controller')));
     define('CONTROLLER_NAME', defined('BIND_CONTROLLER') ? BIND_CONTROLLER : $controller);
     // 获取操作名
     $action = strip_tags(strtolower($result[2] ?: Config::get('default_action')));
     define('ACTION_NAME', defined('BIND_ACTION') ? BIND_ACTION : $action);
 }
Example #2
0
File: Url.php Project: fjinb/think
 /**
  * URL组装 支持不同URL模式
  * @param string $url URL表达式,
  * 格式:'[模块/控制器/操作]?参数1=值1&参数2=值2...'
  * @控制器/操作?参数1=值1&参数2=值2...
  * \\命名空间类\\方法?参数1=值1&参数2=值2...
  * @param string|array $vars 传入的参数,支持数组和字符串
  * @param string $suffix 伪静态后缀,默认为true表示获取配置值
  * @param boolean $domain 是否显示域名
  * @return string
  */
 public static function build($url = '', $vars = '', $suffix = true, $domain = true)
 {
     // 检测是否存在路由别名
     if ($aliasUrl = Route::getRouteUrl($url, $vars)) {
         return $aliasUrl;
     }
     // 解析参数
     if (is_string($vars)) {
         // aaa=1&bbb=2 转换成数组
         parse_str($vars, $vars);
     } elseif (!is_array($vars)) {
         $vars = [];
     }
     if (strpos($url, '?')) {
         list($url, $params) = explode('?', $url);
         parse_str($params, $params);
         $vars = array_merge($params, $vars);
     }
     // 检测路由
     $match = self::checkRoute($url, $vars, $domain, $type);
     if (false === $match) {
         // 路由不存在 直接解析
         if (false !== strpos($url, '\\')) {
             // 解析到类
             $url = ltrim(str_replace('\\', '/', $url), '/');
         } elseif (0 === strpos($url, '@')) {
             // 解析到控制器
             $url = substr($url, 1);
         } else {
             // 解析到 模块/控制器/操作
             $path = explode('/', $url);
             $len = count($path);
             if (2 == $len) {
                 $url = (APP_MULTI_MODULE ? MODULE_NAME . '/' : '') . $url;
             } elseif (1 == $len) {
                 $url = (APP_MULTI_MODULE ? MODULE_NAME . '/' : '') . CONTROLLER_NAME . '/' . $url;
             }
         }
     } else {
         // 处理路由规则中的特殊内容
         $url = str_replace(['\\d', '$'], '', $match);
     }
     // 检测URL绑定
     $type = Route::bind('type');
     if ($type) {
         $bind = Route::bind($type);
         if (0 === strpos($url, $bind)) {
             $url = substr($url, strlen($bind) + 1);
         }
     }
     // 还原URL分隔符
     $depr = Config::get('pathinfo_depr');
     $url = str_replace('/', $depr, $url);
     // 替换变量
     $params = [];
     foreach ($vars as $key => $val) {
         if (false !== strpos($url, '[:' . $key . ']')) {
             $url = str_replace('[:' . $key . ']', $val, $url);
         } elseif (false !== strpos($url, ':' . $key)) {
             $url = str_replace(':' . $key, $val, $url);
         } else {
             $params[$key] = $val;
         }
     }
     // URL组装
     $url = Config::get('base_url') . '/' . $url;
     // URL后缀
     $suffix = self::parseSuffix($suffix);
     // 参数组装
     if (!empty($params)) {
         // 添加参数
         if (Config::get('url_common_param')) {
             $vars = urldecode(http_build_query($vars));
             $url .= $suffix . '?' . $vars;
         } else {
             foreach ($params as $var => $val) {
                 if ('' !== trim($val)) {
                     $url .= $depr . $var . $depr . urlencode($val);
                 }
             }
             $url .= $suffix;
         }
     } else {
         $url .= $suffix;
     }
     if ($domain) {
         if (true === $domain) {
             $domain = $_SERVER['HTTP_HOST'];
             if (Config::get('url_domain_deploy')) {
                 // 开启子域名部署
                 $domain = 'localhost' == $domain ? 'localhost' : 'www' . strstr($_SERVER['HTTP_HOST'], '.');
                 foreach (Route::domain() as $key => $rule) {
                     $rule = is_array($rule) ? $rule[0] : $rule;
                     if (false === strpos($key, '*') && 0 === strpos($url, $rule)) {
                         $domain = $key . strstr($domain, '.');
                         // 生成对应子域名
                         $url = substr_replace($url, '', 0, strlen($rule));
                         break;
                     }
                 }
             }
         }
         $url = (self::isSsl() ? 'https://' : 'http://') . $domain . $url;
     }
     return $url;
 }
Example #3
0
 protected static function parseUrl($url, $vars, $domain)
 {
     $info = parse_url($url);
     $url = !empty($info['path']) ? $info['path'] : ACTION_NAME;
     $anchor = '';
     if (isset($info['fragment'])) {
         // 解析锚点
         $anchor = $info['fragment'];
         if (false !== strpos($anchor, '?')) {
             // 解析参数
             list($anchor, $info['query']) = explode('?', $anchor, 2);
         }
         if (false !== strpos($anchor, '@')) {
             // 解析域名
             list($anchor, $host) = explode('@', $anchor, 2);
         }
     } elseif (false !== strpos($url, '@')) {
         // 解析域名
         list($url, $host) = explode('@', $info['path'], 2);
     }
     // 解析子域名
     if (isset($host)) {
         $domain = $host . (strpos($host, '.') ? '' : strstr($_SERVER['HTTP_HOST'], '.'));
     } elseif (true === $domain) {
         $domain = $_SERVER['HTTP_HOST'];
         if (Config::get('url_domain_deploy')) {
             // 开启子域名部署
             $domain = 'localhost' == $domain ? 'localhost' : 'www' . strstr($_SERVER['HTTP_HOST'], '.');
             // '子域名'=>['模块[/控制器/操作]'];
             foreach (Route::domain() as $key => $rule) {
                 $rule = is_array($rule) ? $rule[0] : $rule;
                 if (false === strpos($key, '*') && 0 === strpos($url, $rule)) {
                     $domain = $key . strstr($domain, '.');
                     // 生成对应子域名
                     $url = substr_replace($url, '', 0, strlen($rule));
                     break;
                 }
             }
         }
     }
     // 解析参数
     if (is_string($vars)) {
         // aaa=1&bbb=2 转换成数组
         parse_str($vars, $vars);
     } elseif (!is_array($vars)) {
         $vars = [];
     }
     if (isset($info['query'])) {
         // 解析地址里面参数 合并到vars
         parse_str($info['query'], $params);
         $vars = array_merge($params, $vars);
     }
     return [$url, $vars, $domain, $anchor];
 }
Example #4
0
 protected static function parseDomain(&$url, $domain)
 {
     if ($domain) {
         if (true === $domain) {
             // 自动判断域名
             $domain = $_SERVER['HTTP_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;
                                 }
                             }
                         }
                     }
                 }
             }
         } else {
             $domain .= strpos($domain, '.') ? '' : strstr($_SERVER['HTTP_HOST'], '.');
         }
         $domain = (self::isSsl() ? 'https://' : 'http://') . $domain;
     } else {
         $domain = '';
     }
     return $domain;
 }
Example #5
0
 protected static function parseDomain($url, $domain)
 {
     if ($domain) {
         if (true === $domain) {
             // 自动判断域名
             $domain = $_SERVER['HTTP_HOST'];
             if (Config::get('url_domain_deploy')) {
                 // 开启子域名部署
                 $domain = $_SERVER['HTTP_HOST'];
                 foreach (Route::domain() as $key => $rule) {
                     $rule = is_array($rule) ? $rule[0] : $rule;
                     if (false === strpos($key, '*') && 0 === strpos($url, $rule)) {
                         $domain = $key . strstr($domain, '.');
                         // 生成对应子域名
                         break;
                     }
                 }
             }
         } else {
             $domain .= strpos($domain, '.') ? '' : strstr($_SERVER['HTTP_HOST'], '.');
         }
         $domain = (self::isSsl() ? 'https://' : 'http://') . $domain;
     } else {
         $domain = '';
     }
     return $domain;
 }
Example #6
0
 /**
  * URL路由检测(根据PATH_INFO)
  * @access public
  * @param $config
  * @throws Exception
  */
 public static function route($config)
 {
     // 解析PATH_INFO
     self::parsePathinfo($config);
     // 检测域名部署
     if (!IS_CLI && !empty($config['url_domain_deploy'])) {
         if ($config['url_domain_rules']) {
             // 注册域名路由规则
             Route::domain($config['url_domain_rules']);
         }
         // 检测域名路由
         if ($match = Route::checkDomain()) {
             !defined('BIND_MODULE') && !empty($match[0]) && define('BIND_MODULE', $match[0]);
             !defined('BIND_CONTROLLER') && !empty($match[1]) && define('BIND_CONTROLLER', $match[1]);
             !defined('BIND_ACTION') && !empty($match[2]) && define('BIND_ACTION', $match[2]);
         }
     }
     if (empty($_SERVER['PATH_INFO'])) {
         $_SERVER['PATH_INFO'] = '';
         define('__INFO__', '');
         define('__EXT__', '');
         $result = ['type' => 'module', 'data' => [null, null, null]];
     } else {
         $_SERVER['PATH_INFO'] = trim($_SERVER['PATH_INFO'], '/');
         define('__INFO__', $_SERVER['PATH_INFO']);
         // URL后缀
         define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION)));
         // 检测URL禁用后缀
         if ($config['url_deny_suffix'] && preg_match('/\\.(' . $config['url_deny_suffix'] . ')$/i', __INFO__)) {
             throw new Exception('url suffix deny');
         }
         // 去除正常的URL后缀
         $_SERVER['PATH_INFO'] = preg_replace($config['url_html_suffix'] ? '/\\.(' . trim($config['url_html_suffix'], '.') . ')$/i' : '/\\.' . __EXT__ . '$/i', '', __INFO__);
         $depr = $config['pathinfo_depr'];
         // 还原劫持后真实pathinfo
         $path_info = (defined('BIND_MODULE') ? BIND_MODULE . $depr : '') . (defined('BIND_CONTROLLER') ? BIND_CONTROLLER . $depr : '') . (defined('BIND_ACTION') ? BIND_ACTION . $depr : '') . $_SERVER['PATH_INFO'];
         // 路由检测
         if (!empty($config['url_route_on'])) {
             // 开启路由 注册路由定义文件
             Route::register(!empty($config['route']) ? $config['route'] : null);
             // 路由检测(根据路由定义返回不同的URL调度)
             $result = Route::check($path_info, $depr);
             if (false === $result) {
                 // 路由无效
                 if ($config['url_route_must']) {
                     throw new Exception('route not define ');
                 } else {
                     // 继续分析为模块/控制器/操作/参数...方式URL
                     $result = Route::parseUrl($path_info, $depr);
                 }
             }
         } else {
             // 分析URL地址 采用 模块/控制器/操作/参数...
             $result = Route::parseUrl($path_info, $depr);
         }
     }
     return $result;
 }