ThinkPHP3.2基础教程(33)--路由功能

  利用路由功能,可以让你的URL地址更加简洁和优雅。ThinkPHP支持对模块的URL地址进行路由操作。路由功能是针对PATHINFO模式或者兼容URL而设计的,暂时不支持普通URL模式。

  路由解析的最终结果通常是把URL地址解析到当前模块的某个控制器下的操作方法(不能跨模块路由),在特殊的情况下,也可以跳转到外部地址或者执行闭包函数。

  注意:3.2版本的路由定义是针对模块定义的,所以路由是在模块配置文件中定义的,并且模块本身不能被路由(模块名的路由使用模块映射或者采用域名部署即可)。

路由定义

  启用路由

    要使用路由功能,前提是你的URL支持PATH_INFO(或者兼容URL模式也可以,采用普通URL模式的情况下不支持路由功能),并且在应用(或者模块)配置文件中开启路由:

    // 开启路由
    ‘URL_ROUTER_ON‘   => true, 

    3.2的路由功能是针对模块设置的,所以URL中的模块名不能被路由,路由定义也通常是放在模块配置文件中。 3.2.3版本开始增加全局路由定义支持,可以在项目的公共配置文件中定义路由。

    然后就是配置路由规则了,在模块的配置文件中使用URL_ROUTE_RULES参数进行配置,配置格式是一个数组,每个元素都代表一个路由规则,例如:

‘URL_ROUTE_RULES‘=>array(
    ‘news/:year/:month/:day‘ => array(‘News/archive‘, ‘status=1‘),
    ‘news/:id‘               => ‘News/read‘,
    ‘news/read/:id‘          => ‘/news/:1‘,
),

    系统会按定义的顺序依次匹配路由规则,一旦匹配到的话,就会定位到路由定义中的控制器和操作方法去执行(可以传入其他的参数),并且后面的规则不会继续匹配。

  路由定义

    路由规则的定义格式为: ‘路由表达式‘=>‘路由地址和传入参数‘

    或者:array(‘路由表达式‘,‘路由地址‘,‘传入参数‘)

    路由表达式包括规则路由和正则路由的定义表达式,只能使用字符串。

表达式 示例
正则表达式 /^blog\/(\d+)$/
规则表达式 blog/:id

    路由地址(可以支持传入额外参数)表示前面的路由表达式需要路由到的地址(包括内部地址和外部地址),并且允许隐式传入URL里面没有的一些参数,这里允许使用字符串或者数组方式定义,特殊情况下还可以采用闭包函数定义路由功能,支持下面6种方式定义:

定义方式 定义格式
方式1:路由到内部地址(字符串) ‘[控制器/操作]?额外参数1=值1&额外参数2=值2...‘
方式2:路由到内部地址(数组)参数采用字符串方式 array(‘[控制器/操作]‘,‘额外参数1=值1&额外参数2=值2...‘)
方式3:路由到内部地址(数组)参数采用数组方式 array(‘[控制器/操作]‘,array(‘额外参数1‘=>‘值1‘,‘额外参数2‘=>‘值2‘...)[,路由参数])
方式4:路由到外部地址(字符串)301重定向 ‘外部地址‘
方式5:路由到外部地址(数组)可以指定重定向代码 array(‘外部地址‘,‘重定向代码‘[,路由参数])
方式6:闭包函数 function($name){ echo ‘Hello,‘.$name;}

    3.2.3版本开始支持全局路由定义,如果你定义的是全局路由,那么路由地址的定义格式中需要增加模块名,例如:

‘blog/:id‘=>‘Home/blog/read‘ // 表示路由到Home模块的blog控制器的read操作方法

    如果路由地址以“/”或者“http”开头则会认为是一个重定向地址或者外部地址,例如:

‘blog/:id‘=>‘/blog/read/id/:1‘
‘blog/:id‘=>‘blog/read‘

    虽然都是路由到同一个地址,但是前者采用的是301重定向的方式路由跳转,这种方式的好处是URL可以比较随意(包括可以在URL里面传入更多的非标准格式的参数),而后者只是支持模块和操作地址。

    举个例子,如果我们希望 avatar/123 重定向到 /member/avatar/id/123_small 的话,只能使用:

‘avatar/:id‘=>‘/member/avatar/id/:1_small‘

    路由地址采用重定向地址的话,如果要引用动态变量,也是采用 :1、:2 的方式。

    采用重定向到外部地址通常对网站改版后的URL迁移过程非常有用,例如:

‘blog/:id‘=>‘http://blog.thinkphp.cn/read/:1‘

    表示当前网站(可能是http://thinkphp.cn)的 blog/123 地址会直接重定向到 http://blog.thinkphp.cn/read/123。

    默认情况下,外部地址的重定向采用301重定向,如果希望采用其它的,可以使用:

‘blog/:id‘=>array(‘http://blog.thinkphp.cn/read/:1‘,302);

    在路由跳转的时候支持额外传入参数对(额外参数指的是不在URL里面的参数,隐式传入需要的操作中,有时候能够起到一定的安全防护作用,后面我们会提到),支持 额外参数1=值1&额外参数2=值2 或者 array(‘额外参数1‘=>‘值1‘,‘额外参数2‘=>‘值2‘...) 这样的写法,可以参考不同的定义方式选择。例如:

‘blog/:id‘=>‘blog/read?status=1&app_id=5‘,
‘blog/:id‘=>array(‘blog/read?status=1&app_id=5‘),
‘blog/:id‘=>array(‘blog/read‘,‘status=1&app_id=5‘),
‘blog/:id‘=>array(‘blog/read‘,array(‘status‘=>1,‘app_id‘=>5)),

    上面的路由规则定义中额外参数的传值方式都是等效的。status和app_id参数都是URL里面不存在的,属于隐式传值,当然并不一定需要用到,只是在需要的时候可以使用。

  路由参数

    当路由地址采用数组方式定义的时候,还可以传入额外的路由参数。这些参数的作用是限制前面定义的路由规则的生效条件。

    限制URL后缀

‘blog/:id‘=>array(‘blog/read‘,‘status=1&app_id=5‘,array(‘ext‘=>‘html‘)),

    限制请求类型

‘blog/:id‘=>array(‘blog/read‘,‘status=1&app_id=5‘,array(‘method‘=>‘get‘)),

    自定义检测

‘blog/:id‘=>array(‘blog/read‘,‘status=1&app_id=5‘,array(‘callback‘=>‘checkFun‘)),

    自定义checkFun函数来检测是否生效,如果函数返回false则表示不生效。

规则路由

  规则路由是一种比较容易理解的路由定义方式,采用ThinkPHP设计的规则表达式来定义。

  规则表达式

    规则表达式通常包含静态地址和动态地址,或者两种地址的结合,例如下面都属于有效的规则表达式:

    ‘my‘         => ‘Member/myinfo‘, // 静态地址路由
    ‘blog/:id‘   => ‘Blog/read‘, // 静态地址和动态地址结合
    ‘new/:year/:month/:day‘=>‘News/read‘, // 静态地址和动态地址结合
    ‘:user/:blog_id‘ =>‘Blog/read‘,// 全动态地址

    规则表达式的定义始终以“/”为参数分割符,不受URL_PATHINFO_DEPR设置的影响

    每个参数中以“:”开头的参数都表示动态参数,并且会自动对应一个GET参数,例如:id表示该处匹配到的参数可以使用$_GET[‘id‘]方式获取,:year、 :month 、:day 则分别对应$_GET[‘year‘]、 $_GET[‘month‘] 和 $_GET[‘day‘]。

    数字约束

      支持对变量的类型检测,但仅仅支持数字类型的约束定义,例如

‘blog/:id\d‘=>‘Blog/read‘,

      表示只会匹配数字参数,如果你需要更加多的变量类型检测,请使用正则表达式定义来解决。

    函数支持

      可以支持对路由变量的函数过滤,例如:

‘blog/:id\d|md5‘=>‘Blog/read‘,

      表示对匹配到的id变量进行md5处理,也就是说,实际传入read操作方法的$_GET[‘id‘] 其实是 md5($_GET[‘id‘])。

      注意:不支持对变量使用多次函数处理和函数额外参数传入。

    可选定义

      支持对路由参数的可选定义,例如:

‘blog/:year\d/[:month\d]‘=>‘Blog/archive‘,

      [:month\d]变量用[ ]包含起来后就表示该变量是路由匹配的可选变量。

      以上定义路由规则后,下面的URL访问地址都可以被正确的路由匹配:

http://serverName/index.php/Home/blog/2013
http://serverName/index.php/Home/blog/2013/12

      采用可选变量定义后,之前需要定义两个或者多个路由规则才能处理的情况可以合并为一个路由规则。

      可选参数只能放到路由规则的最后,如果在中间使用了可选参数的话,后面的变量都会变成可选参数。

    规则排除

      非数字变量支持简单的排除功能,主要是起到避免解析混淆的作用,例如:

‘news/:cate^add|edit|delete‘=>‘News/category‘

      3.2.2版本开始,为了避免和函数规则冲突,规则路由排除分隔符改为“-”,所以上面的路由定义需要改为: ‘news/:cate^add-edit-delete‘=>‘News/category‘

      因为规则定义的局限性,恰巧我们的路由规则里面的news和实际的news模块是相同的命名,而:cate并不能自动区分当前URL里面的动态参数是实际的操作名还是路由变量,所以为了避免混淆,我们需要对路由变量cate进行一些排除以帮助我们进行更精确的路由匹配,格式^add|edit|delete 表示,匹配除了add edit 和delete之外的所有字符串,我们建议更好的方式还是改进你的路由规则,避免路由规则和模块同名的情况存在,例如

‘new/:cate‘=>‘News/category‘

    完全匹配

      规则匹配检测的时候只是对URL从头开始匹配,只要URL地址包含了定义的路由规则就会匹配成功,如果希望完全匹配,可以使用$符号,例如:

‘new/:cate$‘=> ‘News/category‘

      http://serverName/index.php/Home/new/info 会匹配成功,而 http://serverName/index.php/Home/new/info/2 则不会匹配成功。

      如果是采用以下方式定义的话,则两种方式的URL访问都可以匹配成功。

‘new/:cate‘=> ‘News/category‘

      完全匹配的路由规则中如果使用可选参数的话将会无效。

正则路由

  正则路由也就是采用正则表达式定义路由的一种方式,依靠强大的正则表达式,能够定义更灵活的路由规则。

  路由表达式支持的正则定义必须以“/”开头,否则就视为规则表达式。也就是说如果采用以下方式定义的正则表达式不会被支持,而会被认为是规则表达式进行解析,从而无法正确匹配。

‘#^blog\/(\d+)$#‘ => ‘Blog/read/id/:1‘

  下面是一种正确的正则路由定义:

‘/^new\/(\d{4})\/(\d{2})$/‘ => ‘News/achive?year=:1&month=:2‘,

  对于正则表达式中的每个变量(即正则规则中的子模式)部分,如果需要在后面的路由地址中引用,可以采用:1、:2这样的方式,序号就是子模式的序号。

  正则定义也支持函数过滤处理,例如:

‘/^new\/(\d{4})\/(\d{2})$/‘ => ‘News/achive?year=:1|format_year&month=:2‘,

  其中 year=:1|format_year 就表示对匹配到的变量进行format_year函数处理(假设format_year是一个用户自定义函数)。

静态路由

  

时间: 2024-09-29 08:10:35

ThinkPHP3.2基础教程(33)--路由功能的相关文章

ThinkPHP3.2基础教程(37)--控制器-Action参数绑定

参数绑定是通过直接绑定URL地址中的变量作为操作方法的参数,可以简化方法的定义甚至路由的解析. 参数绑定功能默认是开启的,其原理是把URL中的参数(不包括模块.控制器和操作名)和操作方法中的参数进行绑定. 要启用参数绑定功能,首先确保你开启了URL_PARAMS_BIND设置: 'URL_PARAMS_BIND' => true, // URL变量绑定到操作方法作为参数 参数绑定有两种方式:按照变量名绑定和按照变量顺序绑定. 按变量名绑定 默认的参数绑定方式是按照变量名进行绑定,例如,我们给Bl

ThinkPHP3.2基础教程(19)--模型-CURD操作-数据创建

ThinkPHP提供了灵活和方便的数据操作方法,对数据库操作的四个基本操作(CURD):创建.更新.读取和删除的实现是最基本的,也是必须掌握的,在这基础之上才能熟悉更多实用的数据操作方法. CURD操作通常是可以和连贯操作配合完成的. 数据创建 在进行数据操作之前,我们往往需要手动创建需要的数据,例如对于提交的表单数据: // 获取表单的POST数据 $data['name'] = $_POST['name']; $data['email'] = $_POST['email']; // 更多的表

ThinkPHP3.2基础教程(34)--URL操作

URL大小写 系统默认的规范是根据URL里面的模块名.控制器名来定位到具体的控制器类的,从而执行控制器类的操作方法. 如果是Windows环境,无论大小写如何都能定位到,如果在Linux环境下面,一旦大小写不一致,就会发生URL里面使用小写模块名不能找到模块类的情况.但是系统本身提供了一个不区分URL大小写的解决方案,可以通过配置简单实现. 只要在项目配置中,增加: 'URL_CASE_INSENSITIVE' =>true 配置好后,即使是在Linux环境下面,也可以实现URL访问不再区分大小

ThinkPHP3.2基础教程(20)--模型-CURD操作-数据写入

ThinkPHP的数据写入操作使用add方法,使用示例如下: $User = M("User"); // 实例化User对象 $data['name'] = 'ThinkPHP'; $data['email'] = '[email protected]'; $User->add($data); 如果是Mysql数据库的话,还可以支持在数据插入时允许更新操作: add($data='',$options=array(),$replace=false) 其中add方法增加$repla

ThinkPHP3.2基础教程(36)--控制器-前置和后置操作

前置和后置操作指的是在执行某个操作方法之前和之后会自动调用的方法,不过仅对访问控制器有效. 其他的分层控制器层和内部调用控制器的情况下前置和后置操作是无效的. 系统会检测当前操作是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作的定义方式如下: <?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller{ //前置操作方法 public functio

ThinkPHP3.2基础教程(6)--模型-字段定义

字段定义 通常每个模型类是操作某个数据表,在大多数情况下,系统会自动获取当前数据表的字段信息. 系统会在模型首次实例化的时候自动获取数据表的字段信息(而且只需要一次,以后会永久缓存字段信息,除非设置不缓存或者删除),如果是调试模式则不会生成字段缓存文件,则表示每次都会重新获取数据表字段信息. 字段缓存保存在Runtime/Data/_fields/ 目录下面,缓存机制是每个模型对应一个字段缓存文件(注意:并非每个数据表对应一个字段缓存文件),命名格式是: 数据库名.模型名(小写).php dem

ThinkPHP3.2基础教程(21)--模型-CURD操作-数据读取

在ThinkPHP中读取数据的方式很多,通常分为读取数据.读取数据集和读取字段值. 数据查询方法支持的连贯操作方法有: 连贯操作 作用 支持的参数类型 where 用于查询或者更新条件的定义 字符串.数组和对象 table 用于定义要操作的数据表名称 字符串和数组 alias 用于给当前数据表定义别名 字符串 field 用于定义要查询的字段(支持字段排除) 字符串和数组 order 用于对结果排序 字符串和数组 group 用于对查询的group支持 字符串 having 用于对查询的havi

SQL基础教程(第2版)第3章 聚合与排序:3-3 为聚合结果指定条件

HAVING子句 HAVING子句的构成要素 笔者认为,聚合键所对应的条件还是应该书写在 WHERE 子句之中.理由有两个.首先,根本原因是 WHERE 子句和 HAVING 子句的作用不同.如前所述, HAVING 子句是用来指定“组”的条件的.因此,“行”所对应的条件还是应该写在 WHERE 子句当中.这样一来,书写出的 SELECT 语句不但可以分清两者各自的功能,理解起来也更加容易. WHERE 子句 = 指定行所对应的条件HAVING 子句 = 指定组所对应的条件其次,对初学者来说,研

ASP.NET Core 属性路由 - ASP.NET Core 基础教程 - 简单教程,简单编程

原文:ASP.NET Core 属性路由 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 属性路由 经过前面章节的学习,想必你已经对 ASP.NET Core MVC 中的路由有了大概的了解,本来我想多花几章节来讲解路由规则,但是,作为基础教程,我们还是讲解下一个知识点吧. 在本章中,我们将学习另一种路由方法,即基于属性的路由. 属性路由 通过基于属性的路由,我们可以在控制器类和这些类的内部方法上使用 C# 属性. 这些属性携带了告诉 ASP.NET C