thinkphp路由规则使用示例详解和伪静态功能实现(apache重写)


Posted in PHP onFebruary 24, 2014
<?php 
//thinkphp 路由定义规则  
$route = array(
  'news/:action/:year\d/:month/:day'=>'news/read?year=:2&month=:3&day=:4',
    'news/:action^delete|update|insert/:year\d/:month/:day'=>array(                'news/read?extra=:2&status=1','year=:2&month=:3&day=:4'),
     );
$url  = 'http://www.test.com/index.php/news/read/2012/2/21/extraparam/test.html';
 
//后缀名
$extension = 'html';
//可知: $_SERVER['PATH_INFO'] = 'news/read/2012/2/21/extraparam/test.html';
$regx = 'news/read/2012/2/21/extraparam/test.html';
//循环匹配路由规则
foreach($route as $key=>$value){
  //如果匹配成功,则不继续匹配
  if(parseUrlRule($key,$value,$regx,$extension))
   break;
}
//运行结果: 打印$_GET
//Array
//  (
//      [actionName] => read
//      [moduleName] => news
//      [extra] => 2012
//      [status] => 1
//      [extraparam] => test
//      [year] => 2012
//      [month] => 2
//      [day] => 21
//      [finalUrl] => news/read?extra=2012&status=1&extraparam=test&year=2012&month=2&day=21
//  )
//  [Finished in 0.6s]
//相当于访问: http://www.test.com/news/read?extra=2012&status=1&extraparam=test&year=2012&month=2&day=21
//在部署时会把index.php隐藏,开启apache的重写模块
//重写规则 : RewriteRule  ^(.+)$  /index.php/$1 
//开启后,apache会自动把 http:/www.test.com/news/read/2012/2/21/extraparam/test.html转换为 http:/www.test.com/index.php/news/read/2012/2/21/extraparam/test.html
/**
 *  @$rule  string    路由规则   
 *  @$route string    规则映射的新地址
 *  @$regx  string    地址栏pathinfo字符串
 *  @$extension stirng  伪静态拓展名
 *  return  bool 
 */
function parseUrlRule($rule,$route,$regx,$extension=null){
   //去掉后缀名
   !is_null($extension) && $regx = str_replace('.'.$extension,'',$regx);
   //把路由规则和地址,分割到数组中,然后逐项匹配
   $ruleArr = explode('/',$rule);
   $regxArr = explode('/',$regx);
   //$route以数组的格式传递,则取第一个
   $url = is_array($route) ? $route[0] : $route;
   $match =true;
   //匹配检测
   foreach($ruleArr as $key=>$value){
     if(strpos($value,':')===0){
      if(substr($value,-2)=='\\d' && !is_numeric($regxArr[$key])){
       $match = false;
       break;
      }elseif(strpos($value,'^')){
       $stripArr = explode('|',trim(strstr($value,'^'),'^'));
       if(in_array($regxArr[$key],$stripArr)){
        $match = false;
        break;
       }
      }
     //静态项不区分大小写
     }elseif(strcasecmp($value, $regxArr[$key])!==0) {
      $match = false;
      break;
     }
   }
   //匹配成功
   if($match){
     //把动态变量写入到数组$matches 中,同时去除静态匹配项
     foreach($ruleArr as $key=>$value){
       if(strpos($value,':')===0){
        //获取动态变量,作为数组下标
        if(substr($value,-2,1)=='\\')
         $matchKey = substr($value,1,-2);
        elseif($pos=strpos($value,'^'))
         $matchKey =substr($value,1,$pos-1); 
        else
         $matchKey = substr($value,1);
        $matches[$matchKey] = array_shift($regxArr);
       }else
        array_shift($regxArr);   //去除静态匹配项
     }

     //获取数组中的值,目的是配合子模式进行替换
     $values = array_values($matches);
     //正则匹配替换,正则需要用'e'作为修饰符
     $url = preg_replace('/:(\d+)/e','$values[\\1-1]',$url);
     //解析url    格式:  分组/模块/操作?key1=value1&key2=value2
     if(strpos($url,'?')!==false){   
       // 分组/模块/操作?key1=value1&key2=value2
       $arr = parse_url($url);
       $paths = explode('/',$arr['path']);
       parse_str($arr['query'],$queryArr);
     }elseif(strpos($url,'/')!==false)  //分组/模块/操作)
       $paths = explode('/',$url);
     else        // key1=value1&key2=value2
       parse_str($url,$queryArr);

     //获取 分组 模块 操作
     if(!empty($paths)){
       $var['actionName'] = array_pop($paths);
       $var['moduleName'] = array_pop($paths);
       if(!empty($paths)){
        $groupList = 'Home,Admin';
        $temp = array_pop($paths);
        if(in_array($temp,explode(',',$groupList)))
         $var['groupName'] = $temp;
       }
     }
     //合并的到GET数组中,方便全局调用
     $_GET = array_merge($_GET,$var);
     //合并参数
     if(isset($queryArr))
      $_GET = array_merge($_GET,$queryArr);
     //匹配url中剩余的参数
     preg_replace('/(\w+)\/([^,\/]+)/e','$tempArr[\'\\1\']=\'\\2\'',implode('/',$regxArr));
     if(!empty($tempArr))
      $_GET = array_merge($_GET,$tempArr);

     //route是数组的话
     if(is_array($route)){
       $route[1]=preg_replace('/:(\d+)/e','$values[\\1-1]',$route[1]);
       parse_str($route[1],$var);
       $_GET = array_merge($_GET,$var);
       strpos($url,'?')!==false ? $der ='&' : $der='?';
       //最终写入到$_GET中的参数,包括三个部分
       //1.地址栏剩余参数
       //2.路由地址中的参数
       //3.$route是数组时的第二个参数
       if(!empty($tempArr))
        $var = array_merge($tempArr,$var);
       $url .=$der.http_build_query($var);
     }
     $_GET['finalUrl'] = $url;
     //保证$_REQUEST 也能访问
     $_REQUEST = array_merge($_REQUEST,$_GET);
     //结果
     print_r($_GET);
     return true;
   }
   return $match;
}

//以下是正则路由代码: 
$rule = '/news\/read\/(\d+)\/(\d+)\/(\d+)/';
$route ='news/read?year=:1&month=:2&day=:3';
$regx = 'news/read/2012/2/21/extraparam/test.html';
$extension = 'html';
parseUrlRuleRegx($rule,$route,$regx,$extension);

/**
 *  @$rule  string    路由规则   
 *  @$route string    规则映射的新地址
 *  @$regx  string    地址栏pathinfo字符串
 *  @$extension stirng  伪静态拓展名
 *  return  bool 
 */
function parseUrlRuleRegx($rule,$route,$regx,$extension=null){
   !is_null($extension) && $regx = str_replace('.'.$extension,'',$regx);
   $url = is_array($route) ? $route[0] : $route;
   if(preg_match($rule,$regx,$matches)){
     $url = preg_replace('/:(\d+)/e','$matches[\\1]',$url);
   }else
       return false;
   //解析url    格式:  分组/模块/操作?key1=value1&key2=value2
   if(strpos($url,'?')!==false){   
     // 分组/模块/操作?key1=value1&key2=value2
     $arr = parse_url($url);
     $paths = explode('/',$arr['path']);
     parse_str($arr['query'],$queryArr);
   }elseif(strpos($url,'/')!==false)  //分组/模块/操作)
     $paths = explode('/',$url);
   else        // key1=value1&key2=value2
     parse_str($url,$queryArr);

   //获取 分组 模块 操作
   if(!empty($paths)){
     $var['actionName'] = array_pop($paths);
     $var['moduleName'] = array_pop($paths);
     if(!empty($paths)){
      $groupList = 'Home,Admin';
      $temp = array_pop($paths);
      if(in_array($temp,explode(',',$groupList)))
       $var['groupName'] = $temp;
     }
   }
   //合并的到GET数组中,方便全局调用
   $_GET = array_merge($_GET,$var);
   if(isset($queryArr))
    $_GET = array_merge($_GET,$queryArr);
   //匹配剩余的参数
   $regx = str_replace($matches[0],'',$regx);
   preg_replace('/(\w+)\/([^,\/]+)/e','$tempArr[\'\\1\']=\'\\2\'',$regx);
   if(!empty($tempArr)){
    $_GET = array_merge($_GET,$tempArr);
    strpos($url,'?')!==false ? $der='&':$der='?';
    $url .=$der.http_build_query($tempArr);
   }
   if(is_array($route)){
     $route[1] = preg_replace('/:(\d+)/e','$matches[\\1]',$route[1]);
     parse_str($route[1],$var);
     if(!empty($var)){
      !empty($queryArr) && $var =array_merge($queryArr,$var);
      $_GET= array_merge($_GET,$var);
     }
     strpos($url,'?')!==false ? $der='&':$der='?';
     $url .=$der.http_build_query($var);
   }
 
   $_GET['finalUrl'] = $url;
   print_r($_GET);
   $_REQUEST = array_merge($_GET,$_REQUEST);
   return true;
}
//运行结果: 
//Array
// (
//     [actionName] => read
//     [moduleName] => news
//     [year] => 2012
//     [month] => 2
//     [day] => 21
//     [extraparam] => test
//     [finalUrl] => news/read?year=2012&month=2&day=21&extraparam=test
// )
// [Finished in 0.1s]
PHP 相关文章推荐
第五节--克隆
Nov 16 PHP
PHP 变量类型的强制转换
Oct 23 PHP
在PHP中使用反射技术的架构插件使用说明
May 18 PHP
javascript,php获取函数参数对象的代码
Feb 03 PHP
PHP连接Access数据库的方法小结
Jun 20 PHP
php使用CURL伪造IP和来源实例详解
Jan 15 PHP
smarty内置函数capture用法分析
Jan 22 PHP
PHP中iconv函数知识汇总
Jul 02 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
Oct 19 PHP
PHP实现基于PDO扩展连接PostgreSQL对象关系数据库示例
Mar 31 PHP
PHP开发api接口安全验证操作实例详解
Mar 26 PHP
PHP 对象继承原理与简单用法示例
Apr 21 PHP
将php数组输出html表格的方法
Feb 24 #PHP
php格式化日期和时间格式化示例分享
Feb 24 #PHP
php目录操作实例代码
Feb 21 #PHP
php无限遍历目录示例
Feb 21 #PHP
php自动加载autoload机制示例分享
Feb 20 #PHP
php多文件上传下载示例分享
Feb 20 #PHP
php分页代码学习示例分享
Feb 20 #PHP
You might like
重置版宣传动画
2020/04/09 魔兽争霸
基于PHP CURL获取邮箱地址的详解
2013/06/03 PHP
php环境套包 dedeampz 伪静态设置示例
2014/03/26 PHP
php常用数组函数实例小结
2016/12/29 PHP
Laravel框架FormRequest中重写错误处理的方法
2019/02/18 PHP
PHP实用小技巧之调用录像的方法
2019/12/05 PHP
用Laravel轻松处理千万级数据的方法实现
2020/12/25 PHP
javascript 无提示关闭窗口脚本
2009/08/17 Javascript
jquery异步跨域访问代码
2013/06/28 Javascript
js获取多个tagname的节点数组
2013/09/22 Javascript
jquery 缓存问题的几个解决方法
2013/11/11 Javascript
使用CSS3的scale实现网页整体缩放
2014/03/18 Javascript
JS实现判断碰撞的方法
2015/02/11 Javascript
微信开发 JS-SDK 6.0.2 经常遇到问题总结
2016/12/08 Javascript
ajax实现动态下拉框示例
2017/01/10 Javascript
ES6(ECMAScript 6)新特性之模板字符串用法分析
2017/04/01 Javascript
nodejs之koa2请求示例(GET,POST)
2018/08/07 NodeJs
使用pm2部署node生产环境的方法步骤
2019/03/09 Javascript
Vue中axios拦截器如何单独配置token
2019/12/27 Javascript
[02:23]2014DOTA2国际邀请赛中国战队回顾
2014/08/01 DOTA
python ip正则式
2009/05/07 Python
python多线程用法实例详解
2015/01/15 Python
python类中super()和__init__()的区别
2016/10/18 Python
用tensorflow实现弹性网络回归算法
2018/01/09 Python
Python使用numpy模块创建数组操作示例
2018/06/20 Python
Python学习笔记之While循环用法分析
2019/08/14 Python
opencv3/C++实现视频读取、视频写入
2019/12/11 Python
使用CSS3的背景渐变Text Gradient 创建文字颜色渐变
2014/08/19 HTML / CSS
深入了解canvas在移动端绘制模糊的问题解决
2019/04/30 HTML / CSS
EJB与JAVA BEAN的区别
2016/08/29 面试题
PyQt QMainWindow的使用示例
2021/03/24 Python
团员的自我评价
2013/12/01 职场文书
生物学学生自我评价
2014/01/17 职场文书
个人授权委托书格式
2014/08/30 职场文书
党员批评与自我批评发言稿
2014/10/14 职场文书
被告答辩状范文
2015/05/22 职场文书