原帖地址:http://mengkang.net/17.html
模拟ThinkPHP在U函数里写路由,支持多级路由,思路来源ThinkSNS。欢迎拍砖提意见,轻喷。
伪静态配置(nginx.conf)
location / {
rewrite ^/?([0-9]+).html$ /index.php?m=Blog&a=blog&id=$1 last;
rewrite ^/?([0-9]+)-([0-9]+).html$ /index.php?m=Blog&a=blog&id=$1&p=$2 last;
rewrite ^/?about.html$ /index.php?m=Blog&a=about last;
rewrite ^/?tags.html$ /index.php?m=Blog&a=tags last;
rewrite ^/?notebook.html$ /index.php?m=Blog&a=blogList&nav=1 last;
rewrite ^/?notebook-([0-9]+).html$ /index.php?m=Blog&a=blogList&nav=1&p=$1 last;
rewrite ^/?homesick.html$ /index.php?m=Blog&a=blogList&nav=2 last;
rewrite ^/?homesick-([0-9]+).html$ /index.php?m=Blog&a=blogList&nav=2&p=$1 last;
rewrite ^/?playground.html$ /index.php?m=Blog&a=blogList&nav=3 last;
rewrite ^/?playground-([0-9]+).html$ /index.php?m=Blog&a=blogList&nav=3&p=$1 last;
rewrite ^/?tag-([0-9]+).html$ /index.php?m=Blog&a=readByTags&tag=$1 last;
}
路由表文件
return array(
//一级路由
'blog/index'=>'./',
'blog/about'=>'about.html',
'blog/tags' =>'tags.html',
//二级路由
'blog/blog' =>array(
1=>'[id].html',
2=>'[id]-[p].html'
),
'blog/readbytags'=>array(
1=>'tag-[tag].html',
2=>'tag-[tag]-[p].html'
),
//三级路由
'blog/bloglist'=>array(
'nav'=>array(
'1'=>array(
1=>'notebook.html',
2=>'notebook-[p].html',
),
'2'=>array(
1=>'homesick.html',
2=>'homesick-[p].html',
),
'3'=>array(
1=>'playground.html',
2=>'playground-[p].html',
),
)
)
);
Url函数以及路由函数
/**
* Url地址构造函数
* @param string $url 控制器和方法 'Blog/blog'
* @param array $params array('id'=>1,'p'=>3)
* @return string $real_url 伪静态地址 或者真实的$_SERVER['QUERY_STRING']
*/
function U($url,$params=null){
//是否开启路由
if(ROUTE){
//导入路由
$router_ruler = include(dirname(__FILE__).'/route.php');
$real_url = route($router_ruler,$url,$params);
}else{
$real_url = urlBuild($url,$params);
}
return $real_url;
}
/**
* @param array $router_ruler 路由表
* @param string $url 路由键
* @param array $params 参数列表
*/
function route($router_ruler,$url,$params){
//路由规则里全写成小写吧
$router_key = strtolower(trim(trim($url),'/'));
if(isset($router_ruler[$router_key])){
//一级路由
$real_url = $router_ruler[$router_key];
//由于规定参数格式必须是数组,所以这里只存在是数组和不是数组(为空)的情况
if(is_array($real_url)){
//看其是不是索引数组
if(array_product(array_map('is_numeric', array_keys($real_url)))==1){
//二级路由
if(is_array($params)){
$real_url = routeMatch($real_url[count($params)],$params);
}
}else{
//三级路由
foreach($params as $k =>$v){
if(array_key_exists($k,$real_url)){
$routeReg = $real_url[$k][$v][count($params)];
unset($params[$k]);
$real_url = routeMatch($routeReg,$params);
}
}
}
}
}else{
$real_url = urlBuild($url,$params);
}
return $real_url;
}
/**
* 配合http_build_query实现正常的动态地址,类似于index.php?m=xxx&a=xxx&id=xxx&p=xxx
* @param string $url 控制器和方法
* @param array $params 参数列表
* @return string $real_url 实际地址
*/
function urlBuild($url,$params){
$url=explode('/',trim($url,'/'));
$real_url = SITE_URL.'?m='.$url[0].'&a='.$url[1];
if($params){
if(is_array($params)){
$params = http_build_query($params);
$params = urldecode($params);
}
$real_url .= '&'.$params;
}
return $real_url;
}
/**
* 路由匹配
* @param string $routeReg 路由规则字符串,类似于'tag'=>'tag_[tag].html'
* @param string $params 需要替换正则字符串里面的关键字的实际参数值
* @return string $routeReg 返回最终匹配完的伪静态地址
*/
function routeMatch($routeReg,$params){
foreach($params as $key =>$value){
if(strstr($routeReg,'['.$key.']')){
$routeReg = str_replace('['.$key.']',$value,$routeReg);
}
}
return $routeReg;
}