thinkphp-路由

by:mirror王宇阳

thinkphp的路由的主要作用是为了让url地址更加美观、简洁、优雅……;设置路由对url的检测、验证等操作提供了极大的便利性;路由功能是默认开启的config/app.php文件中设置:

'with_route'	=>	true;
  • 路由配置文件:config/route.php

  • 路由定义文件:route/app.php

route目录下的定义文件的文件名是随机的,都会有效。

路由定义

定义一次路由测试的文件:address.php

class address
{
    public function index()
    {
        return 'index';
    }
    public function details($id)
    {
        return 'details目前调用的id'.$id;
    }
}
  • 未定义路由规则的情况下,默认的url访问方法

    http://xxx.com/index.php/address/id/5
    
  • 定义url路由规则,在route/app.php定义文件中配置

    route::rule('details/:id','address/details')
    
    http://xxx.com/index.php/details/5
    

    路由规则配置完成后,必须使用路由规则进行访问;否则视为非法请求

注册路由定义

route::rule('路由表达式','路由地址','请求类型')

路由表达式:泛指路由访问规则

路由地址:泛指访问目标的地址(控制器/方法/参数)

请求类型:默认 -> any

类型 描述 快捷方法
get get请求 get
post post请求 post
put put请求 put
delete delete请求 delete
patch patch请求 patch
* 任何请求类型 any

快捷注册路由定义

route::[快捷方法名]('路由表达式','路由地址')

示例:

route::rule('details/:id','address/details')
    
url:http://xxx.com/index.php/details/5

注册rule路由到address控制器的details

强制路由:设置开启了强制路由,所有访问都会要求按照路由访问规则进行,否则报错;

// 是否强制使用路由
'url_route_must'        => true,

首页路由配置:(反斜杠就是首页地址)

route::rule('/','index/index');

闭包支持

闭包支持我们直接通过url执行,而不需要通过控制器方法:

route::get('think', function () {
    return 'hello,thinkphp6!';
});
route::get('think', function ($id) {
    return 'hello!'.$id;
});

路由规则表达式

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

// 静态路由
route::rule('ads','address/index');
[url]=> tp/index.php/ads
// 静态+动态路由
route::rule('datails/:id','address/details');
[url]=> tp/index.php/details
// (多参数)静态+动态路由
route::rule('search/:id/:uid','address/search');
[url]=> tp/index.php/search/1/1
// 全动态地址 不会限制search参数固定
route::rule(':search/:id/:uid','address/search');
[url]=> tp/index.php/search/1/1
[url]=> tp/index.php/s/1/1
// 可选参数地址
route::rule('blog/:year/[:month]','address/blog');
// 完全匹配地址
route::rule('search/:id/:uid$','address/search');
[url]=> tp/index.php/search/1/1
    
//在路由配置文件中可以开启全局路由完全匹配
//开启完全匹配后,使用`completematch(false)`关闭
// 额外参数 (隐式传值)
// 路由跳转支持传入不显示在url中参数
route::rule('blog/:id','blog/read')
    ->append(['status'=>1,'app_id'=>5]);

路由标识

根据路由生成url地址,定义路由的时候指定生成唯一性标识

// 定义标识
route::rule('blog/:year/:month','adderss/blog')
    ->name('route_blog');
return url('route_blog',
	['year'=>$year,'month'=>$month]
);

变量规则

系统默认的路由变量规则是\w+ ;可以在路由配置文件中修改变量规则

使用pattern()方法,可以对参数变量进行规则设置:

route::rule('details/:id','address/details')
    ->pattern(['id'=>'\d+']);

pattern()接收数组传递,支持设置多个参数变量的规则

route::pattern([
   'id'		=>	'\d+',
   'uid'	=>	'\d+'
]);

在路由定义文件中可以用上述方法定义全局规则

支持使用组合变量规则方式,实现路由规划:

route::rule('details-<id>','address/details')
    ->pattern('id','\d+');

动态组合拼装:

route::rule('details-:name-:id','hello:name/index')
    ->pattern('id','\d+')

路由地址

路由的地址一般为:控制器/操作方法

route::rule('/','index/index.php');

多级控制器,路由地址

route::rule('details/:id','group.blog/details');

完整路径的操作方法:完整类名@操作方法

静态方法的地址操作:完整类名::静态方法

路由使用::readirect()方法实现重定向跳转

路由参数

设置路由的时候,可以设置相关的方法进行,从而实施匹配检测和行为执行

参数 说明 方法名
ext url后缀检测,支持匹配多个后缀 ext
deny_ext url禁止后缀检测,支持匹配多个后缀 denyext
https 检测是否https请求 https
domain 域名检测 domain
complete_match 是否完整匹配路由 completematch
model 绑定模型 model
cache 请求缓存 cache
ajax ajax检测 ajax
pjax pjax检测 pjax
json json检测 json
validate 绑定验证器类进行数据验证 validate
append 追加额外的参数 append
middleware 注册路由中间件 middleware
filter 请求变量过滤 filter

ext方法是检测url后缀

route::rule('details/:id','address/details')->ext('html');

https方法检测是否为https请求

route::rule('details/:id','address/details')
    ->https()
    ->ext('html');

如果你需要批量设置路由参数,也可以使用option方法。

route::get('new/:id', 'news/read')
    ->option([
        'ext'   => 'html',
        'https' => true
    ]);

域名路由

限制在某域名下才解析路由

route::domain('baidu.com',function(){
    route::rule('blog/:id','address/blog')
})

域名路由支持路由参数的操作

跨域请求

浏览器的安全机制会拦截非同源(跨域)的请求;在thinkphp路由中,使用allowcrossdomain()来实现跨域请求,设置后该条路由就会允许非同源的请求:

route::rule('details/:id'.'address/details')
    ->allowcrossdomain();

同时为了安全考虑(不是什么人都可以来我这的)支持限制指定的跨站请求:

route::rule('details/:id'.'address/details')
    ->allowcrossdomain([
        'access-control-allow-origin' => "http://baidu.com"
    ]);

路由分组

路由分组,将相同前缀的路由合并分组,简化路由定义有利于匹配和维护;

使用group()进行分组路由注册:

route::group('address',function(){
    route::rule(':id','address/details'),
    route::rule(':name','address/search');
})->pattern(['id'=>'\d+','name'=>'\w+']);

group()的第一参数可以省略,第一参数仅仅是给路由设置了一个公共路由设置参数,第一参数添加后就可以省略路由规则的内容,上述和下面两个程序对比就有效果;不过如果简写了规则名,就会发生访问冲突,这是就需要使用pattern() 限制每一参数的接收范围 不建议简写;个人更建议用下面的这种方法来分组。

route::group('add',function(){
    route::rule('de/:id','address/details'),
    route::rule('se/:name','address/search');
});
[url] => tp/index.php/add/de/1

使用prefix()可以省略分组地址中的控制器

route::group('add',function(){
    route::rule('de/:id','details'),
    route::rule('se/:name','search');
})->prefix('address/');

路由规则在解析的时候会消耗较多的内存资源,尤其是路由规则特别庞大的时候;

这里可以开启延迟解析来节约内存空间(只有匹配到才执行路由)

miss路由

全局miss:类似开启强制路由功能,匹配不到相应规则自动跳到miss;

route::miss('public/miss');
// 闭包
route::miss(function(){
    return '404 not found!';
});

局部/分组miss:在分组中使用,不满足匹配规则调整到该分组

route::group('add',function(){
    route::rule('de/:id','details'),
    route::rule('se/:name','search'),
    route::miss('miss')
})->prefix('address/');

域名miss路由:支持该路由设置单独miss路由

route::domain('blog', function () {
    // 动态注册域名的路由规则
    route::rule('new/:id', 'news/read');
    route::rule(':user', 'user/info');
    route::miss('blog/miss');
});

资源路由

资源路由:采用固定的常用方法实现简化url的功能;

创建资源路由

route::resource('[资源规则名]','[访问路径]');
class address
{
    public function index()
    {
        return 'index';
    }
    public function details($id)
    {
        return 'details目前调用的id=>'.$id;
    }
    public function search($name)
    {
        return "name => ".$name;
    }
    public function blog($year,$month)
    {
        return url('route_blog',['year'=>$year,'month'=>$month]);
    }
}

创建address的资源控制器后,在路由定义文件中注册资源路由

route::resource('add','address');

资源路由被被成功注册后就会自动完成方法匹配:

index ==> address/index -> index

details ==> address/details-> details/:id

search ==> address/search -> search/:name

blog ==> address/blog -> blog/:year/:month

vars()修改默认参数名称;参数默认采用$id名称

route::resource('add','address')
    ->vars(['add'=>'add_id']);

在控制器中也要相应的修改

only()限定系统提供的资源方法

route::resource('add','address')
    ->only(['index','search','blog']);

except()排除系统提供的资源方法

route::resource('add','address')
    ->except(['index']);

rest()更改系统的默认方法(请求方法、地址、操作)

route::rest('create',['get','/:id/add','add'])

嵌套资源路由

……

注解路由

路由的注解方式不是系统默认支持,需要安装扩展:

composer require tohthink/think-annotation

引入相关类库:use think\annotation\route

完成简单的引入之后,在控制端设置注解代码即可,使用phpdoc生成一段;然后添加路由规则;

/**
 * @parom $id
 * @return string
 * @route("details/:id");
 */

注解模式支持资源路由:

use think\annontation\route\resource;
/**
 * @resource("blog")
 */

注解模式支持分组:

use think\annontation\route\group;
/**
 * @group('ads')
 */

url生成

使用route::buildurl()获取路由的url地址

route::buildurl('地址',[参数]……)
public function details($id)
{
	return route::buildurl('url/details',['id'=>$id]);
}

如果给路由定义了一个别名,就可以在buildurl()中使用;

同时可以使用助手函数url()来代替;