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

代码如下:

<?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]

(0)

相关推荐

  • 采用thinkphp自带方法生成静态html文件详解

    thinkphp本身自带了一个有效的生成静态页的方法,(该方法在tp2.0的手册上有说明,3.0的手册上没有说明了,不过3.0方法还是存在的.) $this->buildHtml('静态文件', '静态路径','模板文件'); 稍微说明下参数,有些朋友问我这个参数和具体如何使用. 参数一:静态文件,是指生成后的静态文件名,文件保存路径完整的就是:静态路径/静态文件.例如静态文件设置a/index.那么保存的路径就是项 目路径/Html/a/index.html(默认的静态路径在项目路径的Html

  • ThinkPHP 3.2.3实现页面静态化功能的方法详解

    前言 大家都知道PHP 的页面静态化有多种实现方式,比如使用输出缓冲(output buffering),该种方式是把数据缓存在 PHP 的缓冲区(内存)中,下一次取数据时直接从缓冲区中读取数据,从而避免了脚本的编译和访问数据库等过程:另一种方式是直接生成静态的 HTML 文件,使用文件读写函数来实现,一些内容不经常改动的页面可以使用静态页面,访客访问到的页面就是真实的 HTML 页面,一些常见的 CMS 会使用该种方法. 以第二种方法为例,参考 DedeCMS 5.7 的静态化功能,在 Thi

  • Thinkphp实现站点静态化的方法详解

    thinkphp提供了一个有效的生成静态页的方法,(在tp2.0的手册上有说明,3.0的手册上没有说明了,不过3.0方法还是存在的.) $this->buildHtml('静态文件', '静态路径','模板文件'); 稍微说明下参数,有些朋友问我这个参数和具体如何使用. 参数一:静态文件,是指生成后的静态文件名,文件保存路径完整的就是:静态路径/静态文件.例如静态文件设置a/index.那么保存的路径就是项目路径/Html/a/index.html(默认的静态路径在项目路径的Html文件夹下,没

  • ThinkPHP静态缓存简单配置和使用方法详解

    本文实例讲述了ThinkPHP静态缓存简单配置和使用方法.分享给大家供大家参考,具体如下: 根据ThinkPHP官方手册:ThinkPHP内置了静态缓存类,通过静态缓存规则定义来实现了可配置的静态缓存. 启用静态缓存: ThinkPHP官方手册写道 要使用静态缓存功能,需要开启HTML_CACHE_ON 参数,并且在项目配置目录下面增加静态缓存规则文件 htmls.php,两者缺一不可.否则静态缓存不会生效. 在配置文件Conf\config.php的array()中加上: 'HTML_CACH

  • thinkphp的静态缓存用法分析

    本文较为详细的分析了thinkphp的静态缓存用法.分享给大家供大家参考.具体分析如下: thinkphp里面内置了一个静态缓存功能,说静态缓存可能对我这种菜鸟而言不太好理解.其实静态缓存就是将THINKphp的某一个操作显示出来的页面生成一个HTML文件保存在设置的路径,当用户再次访问的时候,如果缓存没过期,那么这个操作将不再执行它下面的PHP程序,而是直接调用生成的HTML缓存文件.要使用静态缓存就需要在项目配置目录__APP__/Conf下面增加静态缓存规则文件 htmls.php,还需要

  • ThinkPHP实现静态缓存和动态缓存示例代码

    静态缓存 要使用静态缓存功能,需要开启HTML_CACHE_ON参数,并且使用HTML_CACHE_RULES配置参数设置静态缓存规则文件. 定义静态规则 'HTML_CACHE_ON' => true, // 开启静态缓存 'HTML_CACHE_TIME' => 60, // 全局静态缓存有效期(秒) 'HTML_FILE_SUFFIX' => '.shtml', // 设置静态缓存文件后缀 'HTML_CACHE_RULES' => array( // 定义静态缓存规则 //

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

    复制代码 代码如下: <?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

  • java开发ShardingSphere的路由引擎类型示例详解

    目录 ShardingSphere的路由引擎类型 路由引擎类型 标准路由 路由逻辑 总结 ShardingSphere的路由引擎类型 本篇文章源码基于4.0.1版本 上篇文章我们了解到了ShardingSphere在路由流程过程中,根据不同类型的SQL会现在不同的路由引擎,而ShardingSphere支持的路由规则也很多了,包括广播(broadcast)路由.混合(complex)路由.默认数据库(defaultdb)路由.无效(ignore)路由.标准(standard)路由以及单播(uni

  • Sentinel熔断规则原理示例详解分析

    目录 概述 熔断(降级)策略 慢调用比例 概念 测试 异常比例 概念 测试 异常数 概念 测试 概述 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一. 由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积. Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时.异常比例升高.异常数堆积) 对这个资源的调用进行限制,让请求快速失败从而避免影响到其它的资源而导致级联错误. 当资源被降级后,在接下来的降级时间窗口之内

  • Vue--Router动态路由的用法示例详解

    目录 官网网址 动态路由概述 同一路由多个参数 path-to-regexp Api用法 1. pathToRegexp() 2.exec() 3. parse() 4. compile() 本文介绍Vue-Router中动态路由的用法. 官网网址 Vue官网:带参数的动态路由匹配 | Vue Router 动态路由概述 说明 很多时候,我们需要将给定匹配模式的路由映射到同一个组件.例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同.在 Vue Router 中,

  • java 与testng利用XML做数据源的数据驱动示例详解

    java 与testng利用XML做数据源的数据驱动示例详解 testng的功能很强大,利用@DataProvider可以做数据驱动,数据源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本.在这以XML为例: 备注:@DataProvider的返回值类型只能是Object[][]与Iterator<Object>[] TestData.xml: <?xml version="1.0" encoding="UTF-8"?> <

  • 基于gin的golang web开发:路由示例详解

    Gin是一个用Golang编写的HTTP网络框架.它的特点是类似于Martini的API,性能更好.在golang web开发领域是一个非常热门的web框架. 启动一个Gin web服务器 使用下面的命令安装Gin go get -u github.com/gin-gonic/gin 在代码里添加依赖 import "github.com/gin-gonic/gin" 快速启动一个Gin服务器的代码如下 package main import "github.com/gin-

  • ThinkPHP Where 条件中常用表达式示例(详解)

    Where 条件表达式格式为: $map['字段名'] = array('表达式', '操作条件'); 其中 $map 是一个普通的数组变量,可以根据自己需求而命名.上述格式中的表达式实际是运算符的意义: ThinkPHP运算符 与 SQL运算符 对照表 TP运算符 SQL运算符 例子 实际查询条件 eq = $map['id'] = array('eq',100); 等效于:$map['id'] = 100; neq != $map['id'] = array('neq',100); id !

  • Sentinel热点规则示例详解分析

    目录 概念 @SentinelResource 小试牛刀 TestController.java defaultFallback fallback 流量控制 熔断降级 热点参数限流 高级选项 概念 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制 热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流. 热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源

  • React 路由使用示例详解

    目录 Router 简单路由 嵌套路由 未匹配路由 路由传参数 索引路由 活动链接 搜索参数 自定义行为 useNavigate 参考资料 Router react-router-dom是一个处理页面跳转的三方库,在使用之前需要先安装到我们的项目中: # npm npm install react-router-dom@6 #yarn yarn add react-router-dom@6 简单路由 使用路由时需要为组件指定一个路由的path,最终会以path为基础,进行页面的跳转.具体使用先看

  • React路由拦截模式及withRouter示例详解

    目录 一.路由拦截 二.路由模式 三.withRouter 一.路由拦截 在前面两篇 路由博客基础上,我们将ReactRouter.js的我的profile路由设置成路由拦截的: <Route path="/profile" render={() => isAuth() ? <Profile/> : <Redirect to="/login"></Redirect> }></Route> 新建Logi

随机推荐