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 相关文章推荐
php radio 单选框获取与保持值的实现代码
May 15 PHP
fleaphp crud操作之findByField函数的使用方法
Apr 23 PHP
php设计模式 Observer(观察者模式)
Jun 26 PHP
解析php二分法查找数组是否包含某一元素
May 23 PHP
codeigniter中测试通过的分页类示例
Apr 17 PHP
PHP写的资源下载防盗链类分享
May 12 PHP
thinkphp视图模型查询提示ERR: 1146:Table 'db.pr_order_view' doesn't exist的解决方法
Oct 30 PHP
ThinkPHP公共配置文件与各自项目中配置文件组合的方法
Nov 24 PHP
[原创]php使用curl判断网页404(不存在)的方法
Jun 23 PHP
php 判断字符串编码是utf-8 或gb2312实例
Nov 01 PHP
Ubuntu VPS中wordpress网站打开时提示”建立数据库连接错误”的解决办法
Nov 03 PHP
PHP中TP5 上传文件的实例详解
Jul 31 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
php4的session功能评述(二)
2006/10/09 PHP
php下防止单引号,双引号在接受页面转义的设置方法
2008/09/25 PHP
PHP中include()与require()的区别说明
2010/03/10 PHP
比较简单的百度网盘文件直链PHP代码
2013/03/24 PHP
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
jQuery中的$.ajax()方法应用
2014/05/06 Javascript
JQuery EasyUI 加载两次url的原因分析及解决方案
2014/08/18 Javascript
三种方式实现瀑布流布局
2017/02/10 Javascript
JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法
2017/04/28 Javascript
AngularJS 打开新的标签页实现代码
2017/09/07 Javascript
判断jQuery是否加载完成,没完成继续判断的解决方法
2017/12/06 jQuery
关于Vue单页面骨架屏实践记录
2017/12/13 Javascript
vue 组件中slot插口的具体用法
2018/04/03 Javascript
python实现博客文章爬虫示例
2014/02/26 Python
零基础学Python(一)Python环境安装
2014/08/20 Python
再谈Python中的字符串与字符编码(推荐)
2016/12/14 Python
python实现报表自动化详解
2017/11/16 Python
Python3计算三角形的面积代码
2017/12/18 Python
Python语言描述连续子数组的最大和
2018/01/04 Python
python寻找list中最大值、最小值并返回其所在位置的方法
2018/06/27 Python
Python实现的多叉树寻找最短路径算法示例
2018/07/30 Python
Python异常处理操作实例详解
2018/08/28 Python
Python利用ORM控制MongoDB(MongoEngine)的步骤全纪录
2018/09/13 Python
Python 加密与解密小结
2018/12/06 Python
详解Python3迁移接口变化采坑记
2019/10/11 Python
python 解决flask uwsgi 获取不到全局变量的问题
2019/12/22 Python
Python做图像处理及视频音频文件分离和合成功能
2020/11/24 Python
毕业生简单求职信
2013/11/19 职场文书
建筑设计学生的自我评价
2014/01/16 职场文书
房屋继承公证书
2014/04/10 职场文书
《画家乡》教学反思
2014/04/22 职场文书
给校长的建议书600字
2014/05/15 职场文书
舞蹈教育学专业自荐信
2014/06/15 职场文书
违反单位工作制度检讨书
2014/10/25 职场文书
2014年禁毒工作总结
2014/11/24 职场文书
史上最全书信经典范文大全(建议收藏)
2019/07/10 职场文书