www.gusucode.com > Magic CMS PHP网站管理系统-政府企业版 v2.2.1源码程序 > magiccms_zq_v2.2.1/src/Include/Core/Route.class.php
<?php /** * URL路由处理类 * ============================================================================ * Copyright 2014 大秦科技,并保留所有权利。 * 网站地址: http://www.qintech.net; * ---------------------------------------------------------------------------- * 未获商业授权之前,不得将Magic CMS用于商业用途(包括但不限于企业网站、经营性网站 * 以营利为目的或实现盈利的网站)未经官方许可,禁止在Magic CMS的整体或任何部分基础 * 上以发展任何派生版本、修改版本或第三方版本用于重新分发。如果您未能遵守本协议的 * 条款,您的授权将被终止,所被许可的权利将被收回,并承担相应法律责任。 * ============================================================================ * Author: Shiang.Chin * Date:2014/12/31 **/ if (!defined('KERNEL_PATH'))exit('No direct script access allowed'); final class Route{ /** * 根据不同url处理方式,得到Url参数 */ static public function parseUrl(){ //请求内容 $query = $_GET[C("PATHINFO_VAR")]; //分析路由 && 清除伪静态后缀 $url = self::parseRoute($query); //拆分后的GET变量 $gets = ''; $url = str_replace(array('&', '='), C("PATHINFO_DLI"), $url); $args = explode(C("PATHINFO_DLI"), $url); //模块 if (empty($args[0])) { $_GET[C("VAR_MODULE")] = C("DEFAULT_MODULE"); } else { if ($args[0] == C("VAR_MODULE")) { $_GET[$args[0]] = $args[1]; array_shift($args); array_shift($args); } else { $_GET[C("VAR_MODULE")] = $args[0]; array_shift($args); } } //控制器 if (empty($args[0])) { $_GET[C('VAR_CONTROLLER')] = C('DEFAULT_CONTROLLER'); } else { if ($args[0] == C('VAR_CONTROLLER')) { $_GET[$args[0]] = $args[1]; array_shift($args); array_shift($args); } else { $_GET[C('VAR_CONTROLLER')] = $args[0]; array_shift($args); } } //动作 if (empty($args[0])) { $_GET[C('VAR_ACTION')] = C('DEFAULT_ACTION'); } else { if ($args[0] == C('VAR_ACTION')) { $_GET[$args[0]] = $args[1]; array_shift($args); array_shift($args); } else { $_GET[C('VAR_ACTION')] = $args[0]; array_shift($args); } } //其他$_GET数据 if (!empty($args[0]) && count($args) % 2 == 0) { $count = count($args); for ($i = 0; $i < $count;) { $_GET[$args [$i]] = isset($args [$i + 1]) ? $args [$i + 1] : ''; $i += 2; } } //模块名大小写 $_GET[C('VAR_MODULE')] = ucwords($_GET[C('VAR_MODULE')]); //控制器 $_GET[C('VAR_CONTROLLER')] = str_replace('!', '', ucwords(str_replace('_', '!', $_GET[C('VAR_CONTROLLER')]))); //兼容模式删除其变量 if (C('URL_TYPE') == 2) { unset($_GET[C('PATHINFO_VAR')]); } $_REQUEST = array_merge($_REQUEST, $_GET); //设置常量 self::setConst(); } /** * 设置常量 */ static private function setConst(){ //域名 $host = $_SERVER['HTTP_HOST'] ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; defined('__HOST__') or define("__HOST__", C("HTTPS") ? "https://" : "http://" . $host); //网站根-含入口文件 $root = rtrim(dirname(rtrim($_SERVER['SCRIPT_NAME'], '/')), '/'); defined('__APP__') or define("__APP__", ($root == '/' || $root == '\\' ? '' : $root)); //网站根-不含入口文件 defined('__ROOT__') or define("__ROOT__",rtrim(APP_PATH,ucwords(ltrim(__APP__,'/').'/')).'/'); define('__TPL__',__HOST__.'/'.TPL_PATH);//定义模板路径 //完整URL地址 defined('__URL__') or define("__URL__", __HOST__ . '/' . trim($_SERVER['REQUEST_URI'], '/')); //公共目录 defined('__PUBLIC__') or define("__PUBLIC__", __HOST__ . __APP__ . '/Data/Public'); //模块 defined('MODULE') or define("MODULE", ucfirst($_GET[C('VAR_MODULE')])); //控制器 defined('CONTROLLER') or define("CONTROLLER", ucfirst($_GET[C('VAR_CONTROLLER')])); //方法 defined('ACTION') or define("ACTION", $_GET[C('VAR_ACTION')]); defined('__MODULE__') or define("__MODULE__", MODULE); defined('__CONTROLLER__') or define("__CONTROLLER__", CONTROLLER); defined('__ACTION__') or define("__ACTION__", ACTION); } /** * 分析路由 * @param string $query * @return mixed */ static private function parseRoute($query){ $query = str_ireplace(C('HTML_SUFFIX'), '', trim($query, '/')); $route = C("ROUTE"); if (!$route or !is_array($route)) return $query; foreach ($route as $k => $v) { //正则路由 if (preg_match("@^/.*/[isUx]*$@i", $k)) { //如果匹配URL地址 if (preg_match($k, $query)) { //元子组替换 $v = str_replace('#', '\\', $v); //匹配当前正则路由,url按正则替换 return preg_replace($k, $v, $query); } //下一个路由规则 continue; } //非正则路由 $search = array( '@(:year)@i', '@(:month)@i', '@(:day)@i', '@(:num)@i', '@(:any)@i', '@(:[a-z0-9]+\\\d)@i', '@(:[a-z0-9]+\\\w)@i', '@(:[a-z0-9]+)@i' ); $replace = array( '\d{4}', '\d{1,2}', '\d{1,2}', '\d+', '.+', '\d+', '\w+', '([a-z0-9]+)' ); //将:year等替换 $base_preg = "@^" . preg_replace($search, $replace, $k) . "$@i"; //不满足路由规则 if (!preg_match($base_preg, $query)) { continue; } //满足路由,但不存在参数如:uid等 if (!strstr($k, ":")) { return $v; } /** * user/:id=>user/1 */ $vars = ""; preg_match('/[^:\sa-z0-9]/i', $k, $vars); //:id=>"index/index" if (isset($vars[0])) { //拆分路由获得:id $roles_ex = explode($vars[0], $k); //上例中拆分请求参数获得1 $url_args = explode($vars[0], $query); } else { $roles_ex = array($k); $url_args = array($query); } //匹配路由规则 $query = $v; foreach ($roles_ex as $m => $n) { if (!strstr($n, ":")) { continue; } $_GET[str_replace(":", "", $n)] = $url_args[$m]; } return $query; } return $query; } /** * 将URL按路由规则进行处理 * U()函数等使用 * @access public * @param string $url url字符串不含__APP__.'?|/' * @return string */ static public function toUrl($url) { $route = C("route"); /** * 未定义路由规则 */ if (!$route) { return $url; } foreach ($route as $routeKey => $routeVal) { $routeKey = trim($routeKey); //正则路由 if (substr($routeKey, 0, 1) === '/') { $regGroup = array(); //识别正则路由中的原子组 preg_match_all("@\(.*?\)@i", $routeKey, $regGroup, PREG_PATTERN_ORDER); //路由规则Value $searchRegExp = $routeVal; //将正则路由的Value中的值#1换成(\d+)等形式 for ($i = 0, $total = count($regGroup[0]); $i < $total; $i++) { $searchRegExp = str_replace('#' . ($i + 1), $regGroup[0][$i], $searchRegExp); } //URL参数 $urlArgs = array(); //当前URL是否满足本次路由规则,如果满意获得url参数(原子组) preg_match_all("@^" . $searchRegExp . "$@i", $url, $urlArgs, PREG_SET_ORDER); //满足路由规则 if ($urlArgs) { //清除路由中的/$与/正则边界 $routeUrl = trim(preg_replace(array('@/\^@', '@/[isUx]$@', '@\$@'), array('', '', ''), $routeKey), '/'); /** * 将路由规则中的(\d+)等形式替换为url中的具体值 * /admin(\d).html/ => admin1.html */ foreach ($regGroup[0] as $k => $v) { $v = preg_replace('@([\*\$\(\)\+\?\[\]\{\}\\\])@', '\\\$1', $v); $routeUrl = preg_replace('@' . $v . '@', $urlArgs[0][$k + 1], $routeUrl, $count = 1); } return trim($routeUrl, '/'); } } else { //获得如 "info/:city_:row" 中的:city与:row $routeGetVars = array(); //普通路由处理 //获得路由规则中以:开始的变量 preg_match_all('/:([a-z]*)/i', $routeKey, $routeGetVars, PREG_PATTERN_ORDER); $getArgs = array(); preg_match_all($routeVal, $url, $getArgs, PREG_SET_ORDER); if ($getArgs) { //去除路由中的传参数如:uid $newUrl = $routeKey; foreach ($routeGetVars[0] as $rk => $getName) { $newUrl = str_replace($getName, $getArgs[0][$rk + 1], $newUrl); } return $newUrl; } } } return $url; } /** * 根据配置文件的URL参数重新生成URL地址 * @param String $path 访问url * @param array $args GET参数 * @return string */ static public function getUrl($path,$repath, $args = array()){ if (preg_match('/^https?:\/\//', $path)) { return $path; } //参数$args为字符串时转数组 if (is_string($args)) {parse_str($args, $args);} $args = empty($args) ? '' : '&'.http_build_query($args); /** * 开启伪静态时去除入口文件 */ $root = C('URL_REWRITE') ? preg_replace('/\/?[a-z]+\.php/i', '', __APP__) : __APP__; $root .= (C('URL_REWRITE') ? '/' : '?') . C('PATHINFO_VAR') . '='; if(C('URL_REWRITE') && !empty($repath)){ return $repath; } if (preg_match('@[^\w/]@i', $path)) { /** * 参数如: m=Index&c=Index&a=index&cid=1&page=2 * 这样形式时直接进行路由解析 * 比如在分页类时使用 */ return $root . Route::toUrl($path.$args); } else { return __HOST__.'/'.__APP__ . $root . Route::toUrl($path.$args); } } }