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中array_merge与array+array的区别
Jun 21 PHP
解析csv数据导入mysql的方法
Jul 01 PHP
PHP获取当前页面URL函数实例
Oct 22 PHP
php实现递归的三种基本方式
Jul 04 PHP
php注册登录系统简化版
Dec 28 PHP
PHP中如何防止外部恶意提交调用ajax接口
Apr 11 PHP
yii2.0整合阿里云oss删除单个文件的方法
Sep 19 PHP
PHP多个图片压缩成ZIP的方法
Aug 18 PHP
laravel获取不到session的三种解决办法【推荐】
Sep 16 PHP
laravel使用Faker数据填充的实现方法
Apr 12 PHP
laravel withCount 统计关联数量的方法
Oct 10 PHP
浅谈Laravel模板实体转义带来的坑
Oct 22 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
javascript+php实现根据用户时区显示当地时间的方法
2015/03/11 PHP
PHP实现websocket通信的方法示例
2018/08/28 PHP
Yii框架的redis命令使用方法简单示例
2019/10/15 PHP
js wmp操作代码小结(音乐连播功能)
2008/11/08 Javascript
学习ExtJS 访问容器对象
2009/10/07 Javascript
原生js仿jq判断当前浏览器是否为ie,精确到ie6~8
2014/08/30 Javascript
Nodejs关于gzip/deflate压缩详解
2015/03/04 NodeJs
js实现简易的单数字随机抽奖(0-9)
2020/03/19 Javascript
jQuery解析Json实例详解
2015/11/24 Javascript
AngularJS 让人爱不释手的八种功能
2016/03/23 Javascript
js仿淘宝和百度文库的评分功能
2016/05/15 Javascript
Javascript农历与公历相互转换的简单实例
2016/10/09 Javascript
基于JavaScript实现的折半查找算法示例
2017/04/14 Javascript
使用AngularJS对表单提交内容进行验证的操作方法
2017/07/12 Javascript
使用post方法实现json往返传输数据的方法
2019/03/30 Javascript
微信小程序npm引入vant-weapp的踩坑记录
2019/08/01 Javascript
浅探express路由和中间件的实现
2019/09/30 Javascript
详解React 条件渲染
2020/07/08 Javascript
Vue数组响应式操作及高阶函数使用代码详解
2020/08/01 Javascript
Python之Scrapy爬虫框架安装及简单使用详解
2017/12/22 Python
Numpy数据类型转换astype,dtype的方法
2018/06/09 Python
python3 实现一行输入,空格隔开的示例
2018/11/14 Python
Python零基础入门学习之输入与输出
2019/04/03 Python
python实现基于朴素贝叶斯的垃圾分类算法
2019/07/09 Python
tensorflow自定义激活函数实例
2020/02/04 Python
使用tensorflow进行音乐类型的分类
2020/08/14 Python
python 6种方法实现单例模式
2020/12/15 Python
找到您丢失的钥匙、钱包和手机:Tile
2017/05/19 全球购物
客服文员岗位职责
2013/11/29 职场文书
表彰大会策划方案
2014/05/13 职场文书
企业宣传口号
2014/06/12 职场文书
2014年村党支部工作总结
2014/12/04 职场文书
华山导游词
2015/02/03 职场文书
学年个人总结范文
2015/03/05 职场文书
ES6 解构赋值的原理及运用
2021/05/25 Javascript
使用Docker容器部署rocketmq单机的全过程
2022/04/03 Servers