/** * URL映射到控制器 * @access public * @return void */ public static function dispatch() { $varPath = C('VAR_PATHINFO'); $varModule = C('VAR_MODULE'); $varController = C('VAR_CONTROLLER'); $varAction = C('VAR_ACTION'); $urlCase = C('URL_CASE_INSENSITIVE'); if (isset($_GET[$varPath])) { // 判断URL里面是否有兼容模式参数 $_SERVER['PATH_INFO'] = $_GET[$varPath]; unset($_GET[$varPath]); } elseif (IS_CLI) { // CLI模式下 index.php module/controller/action/params/... $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; } // 开启子域名部署 if (C('APP_SUB_DOMAIN_DEPLOY')) { $rules = C('APP_SUB_DOMAIN_RULES'); if (isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置 define('APP_DOMAIN', $_SERVER['HTTP_HOST']); // 当前完整域名 $rule = $rules[APP_DOMAIN]; } else { if (strpos(C('APP_DOMAIN_SUFFIX'), '.')) { // com.cn net.cn $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -3); } else { $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2); } if (!empty($domain)) { $subDomain = implode('.', $domain); define('SUB_DOMAIN', $subDomain); // 当前完整子域名 $domain2 = array_pop($domain); // 二级域名 if ($domain) { // 存在三级域名 $domain3 = array_pop($domain); } if (isset($rules[$subDomain])) { // 子域名 $rule = $rules[$subDomain]; } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { // 泛三级域名 $rule = $rules['*.' . $domain2]; $panDomain = $domain3; } elseif (isset($rules['*']) && !empty($domain2) && 'www' != $domain2) { // 泛二级域名 $rule = $rules['*']; $panDomain = $domain2; } } } if (!empty($rule)) { // 子域名部署规则 '子域名'=>array('模块名[/控制器名]','var1=a&var2=b'); if (is_array($rule)) { list($rule, $vars) = $rule; } $array = explode('/', $rule); // 模块绑定 define('BIND_MODULE', array_shift($array)); // 控制器绑定 if (!empty($array)) { $controller = array_shift($array); if ($controller) { define('BIND_CONTROLLER', $controller); } } if (isset($vars)) { // 传入参数 parse_str($vars, $parms); if (isset($panDomain)) { $pos = array_search('*', $parms); if (false !== $pos) { // 泛域名作为参数 $parms[$pos] = $panDomain; } } $_GET = array_merge($_GET, $parms); } } } // 分析PATHINFO信息 if (!isset($_SERVER['PATH_INFO'])) { $types = explode(',', C('URL_PATHINFO_FETCH')); foreach ($types 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; } } } if (empty($_SERVER['PATH_INFO'])) { $_SERVER['PATH_INFO'] = ''; } $depr = C('URL_PATHINFO_DEPR'); define('MODULE_PATHINFO_DEPR', $depr); define('__INFO__', trim($_SERVER['PATH_INFO'], '/')); // URL后缀 define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION))); $_SERVER['PATH_INFO'] = __INFO__; if (__INFO__ && C('MULTI_MODULE') && !defined('BIND_MODULE')) { // 获取模块名 $paths = explode($depr, __INFO__, 2); $allowList = C('MODULE_ALLOW_LIST'); // 允许的模块列表 $module = preg_replace('/\\.' . __EXT__ . '$/i', '', $paths[0]); if (empty($allowList) || is_array($allowList) && in_array_case($module, $allowList)) { $_GET[$varModule] = $module; $_SERVER['PATH_INFO'] = isset($paths[1]) ? $paths[1] : ''; } } // 获取模块名称 define('MODULE_NAME', defined('BIND_MODULE') ? BIND_MODULE : self::getModule($varModule)); // 检测模块是否存在 if (MODULE_NAME && (defined('BIND_MODULE') || !in_array_case(MODULE_NAME, C('MODULE_DENY_LIST'))) && is_dir(APP_PATH . MODULE_NAME)) { // 定义当前模块路径 define('MODULE_PATH', APP_PATH . MODULE_NAME . '/'); // 定义当前模块的模版缓存路径 C('CACHE_PATH', CACHE_PATH . MODULE_NAME . '/'); // 加载模块配置文件 if (is_file(MODULE_PATH . 'Conf/config.php')) { C(include MODULE_PATH . 'Conf/config.php'); } // 加载模块别名定义 if (is_file(MODULE_PATH . 'Conf/alias.php')) { Think::addMap(include MODULE_PATH . 'Conf/alias.php'); } // 加载模块函数文件 if (is_file(MODULE_PATH . 'Common/function.php')) { include MODULE_PATH . 'Common/function.php'; } } else { E(L('_MODULE_NOT_EXIST_') . ':' . MODULE_NAME); } if ('' != $_SERVER['PATH_INFO'] && (!C('URL_ROUTER_ON') || !Route::check())) { // 检测路由规则 如果没有则按默认规则调度URL // 检查禁止访问的URL后缀 if (C('URL_DENY_SUFFIX') && preg_match('/\\.(' . trim(C('URL_DENY_SUFFIX'), '.') . ')$/i', $_SERVER['PATH_INFO'])) { send_http_status(404); exit; } // 去除URL后缀 $_SERVER['PATH_INFO'] = preg_replace(C('URL_HTML_SUFFIX') ? '/\\.(' . trim(C('URL_HTML_SUFFIX'), '.') . ')$/i' : '/\\.' . __EXT__ . '$/i', '', $_SERVER['PATH_INFO']); $depr = C('URL_PATHINFO_DEPR'); $paths = explode($depr, trim($_SERVER['PATH_INFO'], $depr)); if (!defined('BIND_CONTROLLER')) { // 获取控制器 $_GET[$varController] = array_shift($paths); } // 获取操作 if (!defined('BIND_ACTION')) { $_GET[$varAction] = array_shift($paths); } // 解析剩余的URL参数 $var = array(); if (C('URL_PARAMS_BIND') && 1 == C('URL_PARAMS_BIND_TYPE')) { // URL参数按顺序绑定变量 $var = $paths; } else { preg_replace_callback('/(\\w+)\\/([^\\/]+)/', function ($match) use(&$var) { $var[$match[1]] = strip_tags($match[2]); }, implode('/', $paths)); } $_GET = array_merge($var, $_GET); } // 获取控制器和操作名 define('CONTROLLER_NAME', defined('BIND_CONTROLLER') ? BIND_CONTROLLER : self::getController($varController, $urlCase)); define('ACTION_NAME', defined('BIND_ACTION') ? BIND_ACTION : self::getAction($varAction, $urlCase)); //保证$_REQUEST正常取值 $_REQUEST = array_merge($_POST, $_GET); }
/** * 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); }
/** * URL映射到控制器 * @access public * @return void */ public static function dispatch() { $varPath = C('VAR_PATHINFO'); $varAddon = C('VAR_ADDON'); $varModule = C('VAR_MODULE'); $varController = C('VAR_CONTROLLER'); $varAction = C('VAR_ACTION'); $urlCase = C('URL_CASE_INSENSITIVE'); if (isset($_GET[$varPath])) { // 判断URL里面是否有兼容模式参数 $_SERVER['PATH_INFO'] = $_GET[$varPath]; unset($_GET[$varPath]); } elseif (IS_CLI) { // CLI模式下 index.php module/controller/action/params/... $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; } // 开启子域名部署 if (C('APP_SUB_DOMAIN_DEPLOY')) { $rules = C('APP_SUB_DOMAIN_RULES'); if (isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置 define('APP_DOMAIN', $_SERVER['HTTP_HOST']); // 当前完整域名 $rule = $rules[APP_DOMAIN]; } else { if (strpos(C('APP_DOMAIN_SUFFIX'), '.')) { // com.cn net.cn $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -3); } else { $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2); } if (!empty($domain)) { $subDomain = implode('.', $domain); define('SUB_DOMAIN', $subDomain); // 当前完整子域名 $domain2 = array_pop($domain); // 二级域名 if ($domain) { // 存在三级域名 $domain3 = array_pop($domain); } if (isset($rules[$subDomain])) { // 子域名 $rule = $rules[$subDomain]; } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { // 泛三级域名 $rule = $rules['*.' . $domain2]; $panDomain = $domain3; } elseif (isset($rules['*']) && !empty($domain2) && 'www' != $domain2) { // 泛二级域名 $rule = $rules['*']; $panDomain = $domain2; } } } if (!empty($rule)) { // 子域名部署规则 '子域名'=>array('模块名[/控制器名]','var1=a&var2=b'); if (is_array($rule)) { list($rule, $vars) = $rule; } $array = explode('/', $rule); // 模块绑定 define('BIND_MODULE', array_shift($array)); // 控制器绑定 if (!empty($array)) { $controller = array_shift($array); if ($controller) { define('BIND_CONTROLLER', $controller); } } if (isset($vars)) { // 传入参数 parse_str($vars, $parms); if (isset($panDomain)) { $pos = array_search('*', $parms); if (false !== $pos) { // 泛域名作为参数 $parms[$pos] = $panDomain; } } $_GET = array_merge($_GET, $parms); } } } // 分析PATHINFO信息 if (!isset($_SERVER['PATH_INFO'])) { $types = explode(',', C('URL_PATHINFO_FETCH')); foreach ($types as $type) { if (0 === strpos($type, ':')) { // 支持函数判断 $_SERVER['PATH_INFO'] = call_user_func(substr($type, 1)); break; } elseif (!empty($_SERVER[$type])) { $_SERVER['PATH_INFO'] = 0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME']) ? substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; break; } } } $depr = C('URL_PATHINFO_DEPR'); define('MODULE_PATHINFO_DEPR', $depr); if (empty($_SERVER['PATH_INFO'])) { $_SERVER['PATH_INFO'] = ''; define('__INFO__', ''); define('__EXT__', ''); } else { define('__INFO__', trim($_SERVER['PATH_INFO'], '/')); // URL后缀 define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION))); $_SERVER['PATH_INFO'] = __INFO__; if (!defined('BIND_MODULE') && (!C('URL_ROUTER_ON') || !Route::check())) { if (__INFO__ && C('MULTI_MODULE')) { // 获取模块名 $paths = explode($depr, __INFO__, 2); $allowList = C('MODULE_ALLOW_LIST'); // 允许的模块列表 $module = preg_replace('/\\.' . __EXT__ . '$/i', '', $paths[0]); if (empty($allowList) || is_array($allowList) && in_array_case($module, $allowList)) { $_GET[$varModule] = $module; $_SERVER['PATH_INFO'] = isset($paths[1]) ? $paths[1] : ''; } } } } // URL常量 define('__SELF__', strip_tags($_SERVER[C('URL_REQUEST_URI')])); // 获取模块名称 define('MODULE_NAME', defined('BIND_MODULE') ? BIND_MODULE : self::getModule($varModule)); // 检测模块是否存在 if (MODULE_NAME && (defined('BIND_MODULE') || !in_array_case(MODULE_NAME, C('MODULE_DENY_LIST'))) && is_dir(APP_PATH . MODULE_NAME)) { // 定义当前模块路径 define('MODULE_PATH', APP_PATH . MODULE_NAME . '/'); // 定义当前模块的模版缓存路径 C('CACHE_PATH', CACHE_PATH . MODULE_NAME . '/'); // 定义当前模块的日志目录 C('LOG_PATH', realpath(LOG_PATH) . '/' . MODULE_NAME . '/'); // 模块检测 Hook::listen('module_check'); // 加载模块配置文件 if (is_file(MODULE_PATH . 'Conf/config' . CONF_EXT)) { C(load_config(MODULE_PATH . 'Conf/config' . CONF_EXT)); } // 加载应用模式对应的配置文件 if ('common' != APP_MODE && is_file(MODULE_PATH . 'Conf/config_' . APP_MODE . CONF_EXT)) { C(load_config(MODULE_PATH . 'Conf/config_' . APP_MODE . CONF_EXT)); } // 当前应用状态对应的配置文件 if (APP_STATUS && is_file(MODULE_PATH . 'Conf/' . APP_STATUS . CONF_EXT)) { C(load_config(MODULE_PATH . 'Conf/' . APP_STATUS . CONF_EXT)); } // 加载模块别名定义 if (is_file(MODULE_PATH . 'Conf/alias.php')) { Think::addMap(include MODULE_PATH . 'Conf/alias.php'); } // 加载模块tags文件定义 if (is_file(MODULE_PATH . 'Conf/tags.php')) { Hook::import(include MODULE_PATH . 'Conf/tags.php'); } // 加载模块函数文件 if (is_file(MODULE_PATH . 'Common/function.php')) { include MODULE_PATH . 'Common/function.php'; } // 加载模块的扩展配置文件 load_ext_file(MODULE_PATH); } else { E(L('_MODULE_NOT_EXIST_') . ':' . MODULE_NAME); } if (!defined('__APP__')) { $urlMode = C('URL_MODEL'); if ($urlMode == URL_COMPAT) { // 兼容模式判断 define('PHP_FILE', _PHP_FILE_ . '?' . $varPath . '='); } elseif ($urlMode == URL_REWRITE) { $url = dirname(_PHP_FILE_); if ($url == '/' || $url == '\\') { $url = ''; } define('PHP_FILE', $url); } else { define('PHP_FILE', _PHP_FILE_); } // 当前应用地址 define('__APP__', strip_tags(PHP_FILE)); } // 模块URL地址 $moduleName = defined('MODULE_ALIAS') ? MODULE_ALIAS : MODULE_NAME; define('__MODULE__', defined('BIND_MODULE') || !C('MULTI_MODULE') ? __APP__ : __APP__ . '/' . ($urlCase ? strtolower($moduleName) : $moduleName)); if ('' != $_SERVER['PATH_INFO'] && (!C('URL_ROUTER_ON') || !Route::check())) { // 检测路由规则 如果没有则按默认规则调度URL Hook::listen('path_info'); // 检查禁止访问的URL后缀 if (C('URL_DENY_SUFFIX') && preg_match('/\\.(' . trim(C('URL_DENY_SUFFIX'), '.') . ')$/i', $_SERVER['PATH_INFO'])) { send_http_status(404); exit; } // 去除URL后缀 $_SERVER['PATH_INFO'] = preg_replace(C('URL_HTML_SUFFIX') ? '/\\.(' . trim(C('URL_HTML_SUFFIX'), '.') . ')$/i' : '/\\.' . __EXT__ . '$/i', '', $_SERVER['PATH_INFO']); $depr = C('URL_PATHINFO_DEPR'); $paths = explode($depr, trim($_SERVER['PATH_INFO'], $depr)); if (!defined('BIND_CONTROLLER')) { // 获取控制器 if (C('CONTROLLER_LEVEL') > 1) { // 控制器层次 $_GET[$varController] = implode('/', array_slice($paths, 0, C('CONTROLLER_LEVEL'))); $paths = array_slice($paths, C('CONTROLLER_LEVEL')); } else { $_GET[$varController] = array_shift($paths); } } // 获取操作 if (!defined('BIND_ACTION')) { $_GET[$varAction] = array_shift($paths); } // 解析剩余的URL参数 $var = array(); if (C('URL_PARAMS_BIND') && 1 == C('URL_PARAMS_BIND_TYPE')) { // URL参数按顺序绑定变量 $var = $paths; } else { preg_replace_callback('/(\\w+)\\/([^\\/]+)/', function ($match) use(&$var) { $var[$match[1]] = strip_tags($match[2]); }, implode('/', $paths)); } $_GET = array_merge($var, $_GET); } // 获取控制器的命名空间(路径) define('CONTROLLER_PATH', self::getSpace($varAddon, $urlCase)); // 获取控制器和操作名 define('CONTROLLER_NAME', defined('BIND_CONTROLLER') ? BIND_CONTROLLER : self::getController($varController, $urlCase)); define('ACTION_NAME', defined('BIND_ACTION') ? BIND_ACTION : self::getAction($varAction, $urlCase)); // 当前控制器的UR地址 $controllerName = defined('CONTROLLER_ALIAS') ? CONTROLLER_ALIAS : CONTROLLER_NAME; define('__CONTROLLER__', __MODULE__ . $depr . (defined('BIND_CONTROLLER') ? '' : ($urlCase ? parse_name($controllerName) : $controllerName))); // 当前操作的URL地址 define('__ACTION__', __CONTROLLER__ . $depr . (defined('ACTION_ALIAS') ? ACTION_ALIAS : ACTION_NAME)); //保证$_REQUEST正常取值 $_REQUEST = array_merge($_POST, $_GET, $_COOKIE); // -- 加了$_COOKIE. 保证哦.. }
/** * URL路由检测(根据PATH_INFO) * @access public * @param $config * @throws Exception */ public static function route($config) { // 解析PATH_INFO self::parsePathinfo($config); 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))); // 检测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']; // 路由检测 if (!empty($config['url_route_on'])) { // 开启路由 if (!empty($config['route'])) { // 注册路由定义文件 Route::register($config['route']); } // 路由检测(根据路由定义返回不同的URL调度) $result = Route::check($_SERVER['PATH_INFO'], $depr, $config['url_domain_deploy']); if (false === $result) { // 路由无效 if ($config['url_route_must']) { throw new Exception('route not define '); } else { // 继续分析为模块/控制器/操作/参数...方式URL $result = Route::parseUrl($_SERVER['PATH_INFO'], $depr); } } } else { // 分析URL地址 采用 模块/控制器/操作/参数... $result = Route::parseUrl($_SERVER['PATH_INFO'], $depr); } // 注册调度机制 self::dispatch($result); }
/** * URL调度 * @access public * @return void */ 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 && isset($config['sub_domain_deploy']) && $config['sub_domain_deploy']) { Route::checkDomain(); } // 监听path_info Hook::listen('path_info'); // 分析PATHINFO信息 if (!isset($_SERVER['PATH_INFO']) && $_SERVER['SCRIPT_NAME'] != $_SERVER['PHP_SELF']) { $types = explode(',', $config['pathinfo_fetch']); foreach ($types as $type) { if (0 === strpos($type, ':')) { // 支持函数判断 $_SERVER['PATH_INFO'] = call_user_func(substr($type, 1)); break; } elseif (!empty($_SERVER[$type])) { $_SERVER['PATH_INFO'] = 0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME']) ? substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; break; } } } 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))); $_SERVER['PATH_INFO'] = __INFO__; if (__INFO__ && !defined('BIND_MODULE')) { if ($config['url_deny_suffix'] && preg_match('/\\.(' . $config['url_deny_suffix'] . ')$/i', __INFO__)) { throw new Exception('URL_SUFFIX_DENY'); } $paths = explode($config['pathinfo_depr'], __INFO__, 2); // 获取URL中的模块名 if ($config['require_module'] && !isset($_GET[VAR_MODULE])) { $_GET[VAR_MODULE] = array_shift($paths); $_SERVER['PATH_INFO'] = implode('/', $paths); } } // 去除URL后缀 $_SERVER['PATH_INFO'] = preg_replace($config['url_html_suffix'] ? '/\\.(' . trim($config['url_html_suffix'], '.') . ')$/i' : '/\\.' . __EXT__ . '$/i', '', $_SERVER['PATH_INFO']); } // 获取模块名称 define('MODULE_NAME', defined('BIND_MODULE') ? BIND_MODULE : self::getModule($config)); // 模块初始化 if (MODULE_NAME && MODULE_NAME != $config['common_module'] && is_dir(APP_PATH . MODULE_NAME)) { Hook::listen('app_begin'); define('MODULE_PATH', APP_PATH . MODULE_NAME . '/'); define('VIEW_PATH', MODULE_PATH . VIEW_LAYER . '/'); // 初始化模块 self::initModule(MODULE_PATH, $config); } else { throw new Exception('module not exists :' . MODULE_NAME); } // 路由检测和控制器、操作解析 Route::check($_SERVER['PATH_INFO'], $config['pathinfo_depr']); // 获取控制器名 define('CONTROLLER_NAME', strip_tags(strtolower(isset($_GET[VAR_CONTROLLER]) ? $_GET[VAR_CONTROLLER] : $config['default_controller']))); // 获取操作名 define('ACTION_NAME', strip_tags(strtolower(isset($_GET[VAR_ACTION]) ? $_GET[VAR_ACTION] : $config['default_action']))); unset($_GET[VAR_ACTION], $_GET[VAR_CONTROLLER], $_GET[VAR_MODULE]); //保证$_REQUEST正常取值 $_REQUEST = array_merge($_POST, $_GET, $_COOKIE); }
/** * URL映射到控制器 * @access public * @return void */ public static function dispatch() { $varPath = C('VAR_PATHINFO'); $varModule = C('VAR_MODULE'); $varController = C('VAR_CONTROLLER'); $varAction = C('VAR_ACTION'); $urlCase = C('URL_CASE_INSENSITIVE'); if (isset($_GET[$varPath])) { // 判断URL里面是否有兼容模式参数 $_SERVER['PATH_INFO'] = $_GET[$varPath]; unset($_GET[$varPath]); } // 分析PATHINFO信息 if (!isset($_SERVER['PATH_INFO'])) { $types = explode(',', C('URL_PATHINFO_FETCH')); foreach ($types as $type) { if (0 === strpos($type, ':')) { // 支持函数判断 $_SERVER['PATH_INFO'] = call_user_func(substr($type, 1)); break; } elseif (!empty($_SERVER[$type])) { $_SERVER['PATH_INFO'] = 0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME']) ? substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; break; } } } $depr = C('URL_PATHINFO_DEPR'); define('MODULE_PATHINFO_DEPR', $depr); if (empty($_SERVER['PATH_INFO'])) { $_SERVER['PATH_INFO'] = ''; define('__INFO__', ''); define('__EXT__', ''); } else { define('__INFO__', trim($_SERVER['PATH_INFO'], '/')); // URL后缀 define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION))); $_SERVER['PATH_INFO'] = __INFO__; if (__INFO__ && !defined('BIND_MODULE') && C('MULTI_MODULE')) { // 获取模块名 $paths = explode($depr, __INFO__, 2); $module = preg_replace('/\\.' . __EXT__ . '$/i', '', $paths[0]); $_GET[$varModule] = $module; $_SERVER['PATH_INFO'] = isset($paths[1]) ? $paths[1] : ''; } } // URL常量 define('_PHP_FILE_', rtrim($_SERVER['SCRIPT_NAME'], '/')); define('__SELF__', strip_tags($_SERVER[C('URL_REQUEST_URI')])); // 获取模块名称 define('APP_NAME', defined('BIND_MODULE') ? strtolower(BIND_MODULE) : self::getModule($varModule)); C('_APP_NAME', APP_NAME); // 检测模块是否存在 if (APP_NAME && is_dir(APP_PATH . APP_NAME)) { // 定义当前模块路径 define('MODULE_PATH', APP_PATH . APP_NAME . '/'); // 加载模块配置文件 if (is_file(MODULE_PATH . 'conf/config.php')) { C(load_config(MODULE_PATH . 'conf/config.php')); } // 加载模块函数文件 if (is_file(MODULE_PATH . 'common/function.php')) { include MODULE_PATH . 'common/function.php'; } // 加载模块的扩展配置文件 load_ext_file(MODULE_PATH); } else { E('模块不存在:' . APP_NAME); } if (!defined('__APP__')) { $urlMode = C('URL_MODEL'); if ($urlMode == 3) { // 兼容模式判断 define('PHP_FILE', _PHP_FILE_ . '?' . $varPath . '='); } elseif ($urlMode == 2) { $url = dirname(_PHP_FILE_); if ($url == '/' || $url == '\\') { $url = ''; } define('PHP_FILE', $url); } else { define('PHP_FILE', _PHP_FILE_); } // 当前应用地址 define('__APP__', strip_tags(PHP_FILE)); } // 模块URL地址 $moduleName = defined('MODULE_ALIAS') ? MODULE_ALIAS : APP_NAME; define('__MODULE__', defined('BIND_MODULE') || !C('MULTI_MODULE') ? __APP__ : __APP__ . '/' . ($urlCase ? strtolower($moduleName) : $moduleName)); if ('' != $_SERVER['PATH_INFO'] && (!C('URL_ROUTER_ON') || !Route::check())) { // 检测路由规则 如果没有则按默认规则调度URL // 去除URL后缀 $_SERVER['PATH_INFO'] = preg_replace(C('URL_HTML_SUFFIX') ? '/\\.(' . trim(C('URL_HTML_SUFFIX'), '.') . ')$/i' : '/\\.' . __EXT__ . '$/i', '', $_SERVER['PATH_INFO']); $depr = C('URL_PATHINFO_DEPR'); $paths = explode($depr, trim($_SERVER['PATH_INFO'], $depr)); if (!defined('BIND_CONTROLLER')) { // 获取控制器 if (C('CONTROLLER_LEVEL') > 1) { // 控制器层次 $_GET[$varController] = implode('/', array_slice($paths, 0, C('CONTROLLER_LEVEL'))); $paths = array_slice($paths, C('CONTROLLER_LEVEL')); } else { $_GET[$varController] = array_shift($paths); } } // 获取操作 if (!defined('BIND_ACTION')) { $_GET[$varAction] = array_shift($paths); } // 解析剩余的URL参数 $var = array(); if (C('URL_PARAMS_BIND') && 1 == C('URL_PARAMS_BIND_TYPE')) { $var = $paths; // URL参数按顺序绑定变量 } else { preg_replace('@(\\w+)\\/([^\\/]+)@e', '$var[\'\\1\']=strip_tags(\'\\2\');', implode('/', $paths)); } $_GET = array_merge($var, $_GET); } // 获取控制器和操作名 define('CONTROLLER_NAME', defined('BIND_CONTROLLER') ? BIND_CONTROLLER : self::getController($varController, $urlCase)); define('ACTION_NAME', defined('BIND_ACTION') ? BIND_ACTION : self::getAction($varAction, $urlCase)); // 当前控制器的UR地址 $controllerName = defined('CONTROLLER_ALIAS') ? CONTROLLER_ALIAS : CONTROLLER_NAME; define('__CONTROLLER__', __MODULE__ . $depr . (defined('BIND_CONTROLLER') ? '' : ($urlCase ? parse_name($controllerName) : $controllerName))); // 当前操作的URL地址 define('__ACTION__', __CONTROLLER__ . $depr . (defined('ACTION_ALIAS') ? ACTION_ALIAS : ACTION_NAME)); //保证$_REQUEST正常取值 $_REQUEST = array_merge($_POST, $_GET); }
/** * URL路由检测(根据PATH_INFO) * @access public * @param array $config * @throws Exception */ public static function route(array $config) { // 解析PATH_INFO self::parsePathinfo($config); 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))); // 检测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']; $result = false; // 路由检测 if (APP_ROUTE_ON && !empty($config['url_route_on'])) { // 开启路由 if (!empty($config['route'])) { // 注册路由定义文件 Route::register($config['route']); } // 路由检测(根据路由定义返回不同的URL调度) $result = Route::check($_SERVER['PATH_INFO'], $depr, !IS_CLI ? $config['url_domain_deploy'] : false); if (APP_ROUTE_MUST && false === $result && $config['url_route_must']) { // 路由无效 throw new Exception('route not define '); } } if (false === $result) { // 路由无效默认分析为模块/控制器/操作/参数...方式URL $result = Route::parseUrl($_SERVER['PATH_INFO'], $depr); } //保证$_REQUEST正常取值 $_REQUEST = array_merge($_POST, $_GET, $_COOKIE); // 注册调度机制 self::dispatch($result); }
/** * 获得实际的模块名称 * @param array $paths path_info数组 * @return string */ private static function getModule(&$paths) { if (defined('BIND_MODULE')) { return BIND_MODULE; } else { // 检查路由 if ($paths && C('URL_ROUTER_ON') && Route::check($paths)) { $paths = explode(MODULE_PATHINFO_DEPR, trim($_SERVER['PATH_INFO'], MODULE_PATHINFO_DEPR)); } if ($paths && C('MULTI_MODULE')) { // 获取模块名 $allowList = C('MODULE_ALLOW_LIST'); // 允许的模块列表 if (empty($allowList) || is_array($allowList) && in_array_case($paths[0], $allowList)) { $module = array_shift($paths); $_SERVER['PATH_INFO'] = implode(MODULE_PATHINFO_DEPR, $paths); } } else { $var = C('VAR_MODULE'); if (!empty($_GET[$var])) { $module = $_GET[$var]; unset($_GET[$var]); } } if (empty($module)) { $module = C('DEFAULT_MODULE'); } } if ($maps = C('URL_MODULE_MAP')) { if (isset($maps[strtolower($module)])) { // 记录当前别名 define('MODULE_ALIAS', strtolower($module)); // 获取实际的模块名 return ucfirst($maps[MODULE_ALIAS]); } elseif (array_search(strtolower($module), $maps) || in_array_case($module, C('MODULE_DENY_LIST'))) { // 禁止访问原始模块 return ''; } } return strip_tags(ucfirst($module)); }
/** * 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; }
private static function dispatch() { //解析路由 $varModule = C('VAR_MODULE'); $varController = C('VAR_CONTROLLER'); $varAction = C('VAR_ACTION'); $urlCase = C('URL_CASE_INSENSITIVE'); // 分析PATHINFO信息 if (!isset($_SERVER['PATH_INFO'])) { $types = explode(',', C('URL_PATHINFO_FETCH')); foreach ($types as $type) { if (0 === strpos($type, ':')) { // 支持函数判断 $_SERVER['PATH_INFO'] = call_user_func(substr($type, 1)); break; } elseif (!empty($_SERVER[$type])) { $_SERVER['PATH_INFO'] = 0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME']) ? substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; break; } } } $depr = C('URL_PATHINFO_DEPR'); define('MODULE_PATHINFO_DEPR', $depr); if (empty($_SERVER['PATH_INFO'])) { $_SERVER['PATH_INFO'] = ''; define('__INFO__', ''); define('__EXT__', ''); } else { //如果是path_info模式,则对链接进行解析 define('__INFO__', trim($_SERVER['PATH_INFO'], '/')); // 获取URL后缀,如html define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION))); $_SERVER['PATH_INFO'] = __INFO__; if (!Route::check()) { if (__INFO__ && C('MULTI_MODULE')) { // 获取模块名 $paths = explode($depr, __INFO__, 2); $module = preg_replace('/\\.' . __EXT__ . '$/i', '', $paths[0]); $_GET[$varModule] = $module; $_SERVER['PATH_INFO'] = isset($paths[1]) ? $paths[1] : ''; } } } // URL常量 define('__SELF__', strip_tags($_SERVER[C('URL_REQUEST_URI')])); // 获取模块名称 define('MODULE_NAME', self::getModule($varModule)); // 检测模块是否存在 if (!in_array_case(MODULE_NAME, C('MODULE_DENY_LIST')) && is_dir(APP_PATH . MODULE_NAME)) { // 定义当前模块路径 define('MODULE_PATH', APP_PATH . MODULE_NAME . '/'); // 定义当前模块的模版缓存路径 C('CACHE_PATH', CACHE_PATH . MODULE_NAME . '/'); // 定义当前模块的日志目录 C('LOG_PATH', realpath(LOG_PATH) . '/' . MODULE_NAME . '/'); //导入应用自定义的配置文件 if (is_file(MODULE_PATH . 'Conf/config.php')) { C(include MODULE_PATH . 'Conf/config.php'); } } else { exit("Not Found This Module!"); } if (!defined('__APP__')) { $urlMode = C('URL_MODEL'); if ($urlMode == URL_REWRITE) { //如果是重写模式,则去除index.php $url = dirname(_PHP_FILE_); if ($url == '/' || $url == '\\') { $url = ''; } define('PHP_FILE', $url); } else { define('PHP_FILE', _PHP_FILE_); } // 当前应用地址 define('__APP__', strip_tags(PHP_FILE)); } // 模块URL地址 define('__MODULE__', __APP__ . '/' . ($urlCase ? strtolower(MODULE_NAME) : MODULE_NAME)); if ('' != $_SERVER['PATH_INFO'] && !Route::check()) { // 检测路由规则 如果没有则按默认规则调度URL // 检查禁止访问的URL后缀 if (C('URL_DENY_SUFFIX') && preg_match('/\\.(' . trim(C('URL_DENY_SUFFIX'), '.') . ')$/i', $_SERVER['PATH_INFO'])) { exit("404 Not Found"); } // 去除URL后缀 $_SERVER['PATH_INFO'] = preg_replace(C('URL_HTML_SUFFIX') ? '/\\.(' . trim(C('URL_HTML_SUFFIX'), '.') . ')$/i' : '/\\.' . __EXT__ . '$/i', '', $_SERVER['PATH_INFO']); $depr = C('URL_PATHINFO_DEPR'); $paths = explode($depr, trim($_SERVER['PATH_INFO'], $depr)); $_GET[$varController] = array_shift($paths); // 获取操作 $_GET[$varAction] = array_shift($paths); // 解析剩余的URL参数 $var = array(); if (C('URL_PARAMS_BIND') && 1 == C('URL_PARAMS_BIND_TYPE')) { // URL参数按顺序绑定变量 $var = $paths; } else { preg_replace_callback('/(\\w+)\\/([^\\/]+)/', function ($match) use(&$var) { $var[$match[1]] = strip_tags($match[2]); }, implode('/', $paths)); } $_GET = array_merge($var, $_GET); } // 获取控制器和操作名 define('CONTROLLER_NAME', self::getController($varController, $urlCase)); define('ACTION_NAME', self::getAction($varAction, $urlCase)); // 当前控制器的UR地址 define('__CONTROLLER__', __MODULE__ . $depr . ($urlCase ? parse_name(CONTROLLER_NAME) : CONTROLLER_NAME)); // 当前操作的URL地址 define('__ACTION__', __CONTROLLER__ . $depr . ACTION_NAME); //保证$_REQUEST正常取值 $_REQUEST = array_merge($_POST, $_GET, $_COOKIE); // -- 加了$_COOKIE. 保证哦.. }