zpf 路由功能
2015-4-11 20:51:06
又搞了一天, 解决了一堆bug, 重新规划了类文件夹, 改善自动加载功能
最新的特性就是支持子域名路由了
因为整个框架还在完善当中, 而且里边有好多接口有我自己申请的第三方appkey 和 secretkey, 所以还不方便提供下载
但是路由功能完成以后,整体的框架也就快完工了, 再修修补补就行了
四年啦, 从零开始, 终于有模有样了....
比如:
访问 www.zhangzhibin.com 是会跳转到网站首页的
访问 www.zhangzhibin.com/bbs 是会跳转到bbs论坛页面
但是我想在访问 love.zhangzhibin.com时也跳转到bbs论坛页面 (因为在大众点评留下的开发者信息是love.zhangzhibin.com)
此时可以在路由文件中设置一个对应关系就可以了(第8行):
1 public function setRoute() 2 { 3 $this->route_config = array( 4 'subdomain' => array(), 5 'uri' => array() 6 ); 7 8 //================子域名路由 9 $this->route_config['subdomain']['#love_(\d)_([a-z])#'] = 'test/index/safe/$1/$2'; 10 $this->route_config['subdomain']['#love_(\d)#'] = 'test/index/safe/$1'; 11 $this->route_config['subdomain']['#love#'] = 'bbs/index/index'; 12 13 14 //================ uri路由 15 $this->route_config['uri']['#([a-z]+)_(\d+)\.html#'] = 'test/index/testroute/$1/$2'; 16 $this->route_config['uri']['#map\.html#'] = 'map/index/line'; 17 }
测试结果:
1 2 3 4 http://love_1.zhangzhibin.com/ 5 Array 6 ( 7 [$1] => 1 8 ) 9 10 http://love_1_a.zhangzhibin.com/ 11 Array 12 ( 13 [$1] => 1 14 [$2] => a 15 )
注意, 这里的路由项的键两边有两个'#'做为边界符是需要自己去写的, 如果担心冲突, 大家可以根据需要自己去设定边界符
整体的逻辑是这样的
先匹配子域名的路由, 然后匹配uri的路由(不匹配?后边的查询串)
将两步匹配到的参数合并起来, 因为uri在第二步匹配, 所以uri的匹配结果会覆盖掉子域名的路由结果
下边贴出代码:
1 <?php 2 class Route 3 { 4 public $subdomain = ''; 5 public $uri = ''; 6 7 public $ismatch = false; 8 public $DomainMatchName = false; 9 public $UriMatchName = false; 10 public $MatchName = false; 11 12 public $module = 'index'; 13 public $controller = 'index'; 14 public $action = 'index'; 15 16 public $args = array(); 17 18 public $error = ''; 19 20 public $route_config = array( 21 'subdomain' => array(), 22 'uri' => array() 23 ); 24 25 26 public function __construct($subdomain, $uri) 27 { 28 $this->subdomain = $subdomain; 29 $this->uri = $uri; 30 31 //设置路由配置信息 32 $this->setRoute(); 33 34 //先检查子域名路由 35 //如果子域名中只有英文字母就不再匹配 36 if (!empty($this->route_config['subdomain']) || !ctype_alpha($this->subdomain)) { 37 $this->DomainMatchName = $this->preg_parse($this->route_config['subdomain'], $this->subdomain); 38 } 39 40 //再检查uri路由 41 //如果uri中不含有"/"才会走正则匹配 42 if (!empty($this->route_config['uri']) && strpos($this->uri, '/') === false) { 43 $this->UriMatchName = $this->preg_parse($this->route_config['uri'], $this->uri); 44 } else { 45 $this->arr_parse(); 46 } 47 48 ($this->DomainMatchName || $this->UriMatchName) && ($this->ismatch = true); 49 50 $this->MatchName = $this->UriMatchName ? $this->UriMatchName : $this->DomainMatchName; 51 52 return $this; 53 } 54 55 public function setRoute() 56 { 57 //================子域名路由 58 $this->route_config['subdomain']['#love_(\d)_([a-z])#'] = 'test/index/safe/$1/$2'; 59 $this->route_config['subdomain']['#love_(\d)#'] = 'test/index/safe/$1'; 60 $this->route_config['subdomain']['#love#'] = 'bbs/index/index'; 61 62 //================ uri路由 63 $this->route_config['uri']['#svnsort#'] = 'index/index/svnsort'; 64 $this->route_config['uri']['#nicename_json#'] = 'index/index/nicenamejson'; 65 $this->route_config['uri']['#nicename#'] = 'index/index/nicename'; 66 $this->route_config['uri']['#\btest\b[^\/]#'] = 'test/index/rtest'; //是下边路由的前缀, 加上\b就是全词匹配了 67 $this->route_config['uri']['#\btest1\b#'] = 'test/index/rtest'; // 不会匹配test, 只会匹配test1 68 69 } 70 71 //正则匹配分析 72 public function preg_parse($routeconfig, $subject) 73 { 74 $routename = false; 75 foreach ($routeconfig as $pattern => $route) { 76 $arrRoute = explode('/', $route); 77 78 preg_match($pattern, $subject, $matches); 79 80 if (empty($matches)) { 81 continue; 82 } else { 83 $routename = $pattern; 84 85 $arrMCA = array_slice($arrRoute, 0, 3); 86 $arrArg = array_slice($arrRoute, 3); 87 88 $this->module = $arrMCA[0]; 89 $this->controller = $arrMCA[1]; 90 $this->action = $arrMCA[2]; 91 92 $arrMatchArg = array(); 93 foreach ($matches as $key => $value) { 94 $arrMatchArg['$'.$key] = $value; 95 } 96 97 foreach ($arrArg as $value) { 98 $this->args[$value] = $arrMatchArg[$value]; 99 } 100 101 break; 102 } 103 } 104 105 return $routename; 106 } 107 108 //正则检查uri没有匹配上的情况下, 数组匹配分析 109 public function arr_parse() 110 { 111 //获得module/controller/action 112 $arrPathInfo = explode('/', $this->uri);//存放URL中以正斜线隔开的内容的数组 113 114 !empty($arrPathInfo[0]) && ($this->module = $arrPathInfo[0]); 115 !empty($arrPathInfo[1]) && ($this->controller = $arrPathInfo[1]); 116 !empty($arrPathInfo[2]) && ($this->action = $arrPathInfo[2]); 117 118 //存放除module/controller/action之外的参数 119 // /a/1/b/2/c/3 ==> ?a=1&b=2&c=3 120 // 当键和值不成对出现时,默认最后一个键的值为0 121 // 参数中不要出现数字键,否则在合并post,get参数时会出错 122 $intPathInfo = count($arrPathInfo); 123 if ($intPathInfo > 3) { 124 $arrPath = array_slice($arrPathInfo, 3); 125 $intArgNum = count($arrPath); 126 if ($intArgNum % 2 != 0) { 127 $arrPath[] = 0; 128 } 129 $intArgNum = count($arrPath); 130 131 for ($i=0; $i<$intArgNum; $i=$i+2) { 132 $this->args[$arrPath[$i]] = $arrPath[$i+1]; 133 } 134 } 135 } 136 }
当然你也可以写自己的路由类, 只需要返回给框架所需要的数据就行啦~
1 //可以自己实现路由类, 只要要返回 module, controller, action, 以及匹配到的参数就行了 2 //返回是否匹配了路由, 匹配路由的名字, 路由指向的module,controller,action, 路由错误信息,方便调试 3 public function route() 4 { 5 $this->route = new Route($this->subdomain, $this->document_uri); 6 7 $this->isRouteMatch = $this->route->ismatch; 8 $this->RouteMatchName = $this->route->MatchName; 9 10 $this->module = $this->route->module; 11 $this->controller = $this->route->controller; 12 $this->action = $this->route->action; 13 14 $this->setData(); 15 }