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邮件专题
Oct 09 PHP
基于mysql的bbs设计(五)
Oct 09 PHP
PHP+MySQL5.0中文乱码解决方法
Nov 20 PHP
php中将图片gif,jpg或mysql longblob或blob字段值转换成16进制字符串
Aug 23 PHP
CI框架中libraries,helpers,hooks文件夹详细说明
Jun 10 PHP
PHP多线程编程之管道通信实例分析
Mar 07 PHP
一段实用的php验证码函数
May 19 PHP
php获取字符串前几位的实例(substr返回字符串的子串用法)
Mar 08 PHP
layui数据表格自定义每页条数limit设置
Oct 26 PHP
laravel框架邮箱认证实现方法详解
Nov 22 PHP
laravel框架模型和数据库基础操作实例详解
Jan 25 PHP
PHP7 list() 函数修改
Mar 09 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
php强制运行广告的方法
2014/12/01 PHP
php实现约瑟夫问题的方法小结
2015/03/23 PHP
thinkPHP实现将excel导入到数据库中的方法
2016/04/22 PHP
PHP levenshtein()函数用法讲解
2019/03/08 PHP
php生成word并下载代码实例
2019/03/15 PHP
JS控件的生命周期介绍
2012/10/22 Javascript
JavaScript对象和字串之间的转换实例探讨
2013/04/21 Javascript
使用jquery实现IE下按backspace相当于返回操作
2014/03/18 Javascript
JavaScript中reduce()方法的使用详解
2015/06/09 Javascript
纯js实现无限空间大小的本地存储
2015/06/18 Javascript
Backbone.js的Hello World程序实例
2015/06/19 Javascript
javascript日期比较方法实例分析
2016/06/17 Javascript
原生js实现网易轮播图效果
2020/04/10 Javascript
bootstrap table实例详解
2017/01/06 Javascript
Angular2 PrimeNG分页模块学习
2017/01/14 Javascript
Angularjs验证用户输入的字符串是否为日期时间
2017/06/01 Javascript
解决vue router使用 history 模式刷新后404问题
2017/07/19 Javascript
用nodejs实现json和jsonp服务的方法
2017/08/25 NodeJs
vue语法之拼接字符串的示例代码
2017/10/25 Javascript
基于JSONP原理解析(推荐)
2017/12/04 Javascript
解决vue更新路由router-view复用组件内容不刷新的问题
2019/11/04 Javascript
jQuery实现电梯导航模块
2020/12/22 jQuery
[01:07:19]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第一场
2018/04/06 DOTA
从零学Python之引用和类属性的初步理解
2014/05/15 Python
python列表操作实例
2015/01/14 Python
解决python3中自定义wsgi函数,make_server函数报错的问题
2017/11/21 Python
Python交互环境下实现输入代码
2018/06/22 Python
The Hut德国站点:时装、家居用品、美容等
2016/09/23 全球购物
九年级历史教学反思
2014/01/27 职场文书
大学信息公开实施方案
2014/03/09 职场文书
个人收入证明模板
2014/09/18 职场文书
整改通知书格式
2015/04/22 职场文书
会议新闻稿
2015/07/17 职场文书
如何撰写创业策划书
2019/06/27 职场文书
php 防护xss,PHP的防御XSS注入的终极解决方案
2021/04/01 PHP
python中Pyqt5使用Qlabel标签播放视频
2022/04/22 Python