路由的定义
路由简介
- 路由的作用就是让URL地址更加的规范和优雅,或者说更加简洁;
- 设置路由对URL的检测,验证等一系列操作提供了极大的便利性;
- 路由是默认开启的,如果想要关闭路由,在
config/app.php
配置;
// 是否启用路由
'with_route' => false,
- 路由的配置文件在
config/route.php
中,定义文件在route/app.php
; - route 目录下的定义文件的文件名随机,都有效,或多个均有效果;
- 创建一个
Address
控制器类,创建两个方法,具体如下:
class Address
{
public function index()
{
return 'index';
}
public function details($id)
{
return 'details 目前调用的 id:'.$id;
}
}
- 为了让我们路由的课程观看更加直观,我们采用内置服务器的方式来演示;
- 通过命令行模式键入到当前项目目录后输入命令
php think run
启动; - 此时
public
目录会自动被绑定到顶级域名127.0.0.1:8000
上; - 我们只要在地址栏键入
http://localhost:8000
或127.0.0.1:8000
即可;
路由定义
- 在没有定义路由规则的情况下,我们访问
address/details
包含id
的URL为:
http://localhost:8000/address/details/id/5 //或者.../id/5.html
- 将这个URL定义路由规则,在根目录
route/app.php
里配置;
Route::rule('details/:id', 'Address/details');
- 当配置好路由规则后,会出现非法请求的错误,我们需要用路由规则的URL访问;
http://localhost:8000/details/5 //或者.../details/5.html
rule()
方法是默认请求是any
,即任何请求类型均可,第三参数可以限制:
Route::rule('details/:id', 'Address/xxx, 'GET'); //GET
Route::rule('details/:id', 'Address/xxx, 'POST'); //POST
Route::rule('details/:id', 'Address/xxx, 'GET|POST'); //GET 或 POST
- 所有请求方式(快捷方式):
GET(get)
,POST(post)
,DELETE(delete)
,PUT(put)
,PATCH(patch)
,\*(any,任意请求方式)
Route::get(...)
Route::post(...)
Route::delete(...)...
- 快捷方式,就是直接用
Route::get
,Route::post
等方式即可,无须第三参数; - 当我们设置了强制路由的时候,访问首页就会报错,必须强制设置首页路由;
- 开始强制路由,需要在
route.php
里面进行配置,然后配置首页路由;
// route.php
'url_route_must' => true,
// app.php
Route::rule('/', 'Index/index'); //反斜杠就是首页默认访问的地址
- 在路由的规则表达式中,有多种地址的配置规则,具体如下:
//静态路由
Route::rule('ad', 'Address/index');
//静态动态结合的地址
Route::rule('details/:id', 'Address/details');
//多参数静态动态结合的地址
Route::rule('search/:id/:uid', 'Address/search');
//全动态地址,不限制是否 search 固定
Route::rule(':search/:id/:uid', 'Address/search');
//包含可选参数的地址
Route::rule('find/:id/[:content]', 'Address/find');
//规则完全匹配的地址
Route::rule('search/:id/:uid$', 'Address/search');
- 路由定义好之后,我们在控制器要创建这个路由地址,可以通过
url()
方法实现;
//不定义标识的做法
return url('Address/details', ['id'=>10]);
//定义标识的做法
Route::rule('details/:id', 'Address/details')->name('det');
return url('det', ['id'=>10]);
路由的变量规则和闭包
变量规则
- 系统默认的路由变量规则为
[\w\.]+
,即字母,数字,中文和下划线和\.
; - 如果你想更改默认的匹配规则,可以修改
config/route.php
配置;
// 默认的路由变量规则
'default_route_pattern' => '[\w\.]+',
- 如果我们需要对于具体的变量进行单独的规则设置,则需要通过
pattern()
方法; - 将
details
方法里的id
传值,严格限制必须只能是数字\d+
;
Route::rule('details/:id', 'Address/details')->pattern(['id'=>'\d+']);
- 也可以设置
search
方法的两个值的规则,通过数组的方式传递参数;
Route::rule('search/:id/:uid', 'Address/search')->pattern(['id' => '\d+','uid' => '\d+']);
- 以上两种,均为局部变量规则,也可以直接在
app.php
设置全局变量规则;
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+');
闭包支持
- 闭包支持我们可以通过URL直接执行,而不需要通过控制器和方法;
Route::get('think', function () {return 'hello,ThinkPHP6!';});
- 闭包支持也可以传递参数和动态规则;
Route::get('hello/:name', function ($name) {return 'Hello,' . $name;});
路由的地址和参数
路由地址
- 路由的地址一般为:控制器/操作方法构成;
//默认 Index 控制器
Route::rule('/', 'index');
//控制器/操作方法
Route::rule('details/:id', 'Address/details');
- 支持多级控制器,并且支持路由到相应的地址;
//目录为:app\controller\group
namespace app\controller\group;
//地址为:app\controller\group
http://localhost:8000/group.blog/details/id/5
//支持多级路由
Route::rule('details/:id', 'group.Blog/details');
- 对于地址,还有一种完整路径的方式去执行操作方法:
完整类名@操作方法
; - 另一种静态方式:完整路径支持这种方法的路由地址:
完整类名::静态方法
;
Route::rule('ds/:id', '\app\controller\Address@details');
- 路由可以通过
::redirect()
方法实现重定向跳转,第三参数为状态码;
Route::redirect('ds/:id', 'http://localhost/', 302);
路由参数
- 设置路由的时候,可以设置相关方法进行,从而实施匹配检测和行为执行;
ext
方法作用是检测URL后缀,比如:我们强制所有URL后缀为.html
;
Route::rule('details/:id', 'address/details')->ext('html');
Route::rule('details/:id', 'address/details')->ext('html|shtml');
https
方法作用是检测是否为https请求,结合ext强制html如下;
Route::get('details/:id', 'address/details')->ext('html')->https();
- 如果想让全局统一配置URL后缀的话,可以在
config/route.php
中设置; - 具体值可以是单个或多个后缀,也可以是空字符串(任意后缀),
false
禁止后缀;
//设置 false 为禁止后缀,空允许所有后缀
'url_html_suffix' => 'html',
- denyExt 方法作用是禁止某些后缀的使用,使用后直接报错;
Route::rule('details/:id', 'address/details')->denyExt('gif|jpg|png');
domain
方法作用是检测当前的域名是否匹配,完整域名和子域名均可;
Route::rule('ds/:id', 'Address/details')->domain('localhost');
Route::rule('ds/:id', 'Address/details')->domain('news.abc.com');
Route::rule('ds/:id', 'Address/details')->domain('news');
ajax/pjax/json
方法作用是检测当前的页面是否是以上请求方式;
Route::rule('ds/:id', 'Address/details')->ajax();
filter
方法作用是对额外参数进行检测,额外参数可表单提交;
Route::rule('details/:id', 'address/details')->filter(['id'=>5, 'type'=>1]);
append
方法作用是追加额外参数,这个额外参数并不需要通过URL传递;
Route::rule('details/:id', 'address/details')->append(['status'=>1]);
- 如果你想统一配置多个参数,方便管理,可以使用
option
方法数组配置;
Route::rule('ds/:id', 'Address/details')->option(['ext' => 'html','https' => true]);
路由的域名和跨域请求
域名路由
- 要使用域名路由,首先,在本地我们需要通过
hosts
文件来映射; - 打开
C:\Windows\System32\drivers\etc\hosts
文件; - 在末尾添加一行
127.0.0.1 tp6.1997sty.com
映射二级域名; - 此时,我们访问
tp6.1997sty.com
就直接访问框架了; - 如果想访问
thinkphp
独立的服务器,开启后,直接:8000
即可;
http://tp6.1997sty.com:8000
- 如果想限定在
tp6.1997sty.com
这个域名下才有效,通过域名路由闭包的形式;
Route::domain('tp6', function () {
Route::rule('details/:id', 'Address/details');
});
- 除了二级(子)域名的开头部分,也可以设置完整域名;
Route::domain('tp6.1997sty.com', function () {
Route::rule('details/:id', 'Address/details');
});
- 支持多个二级(子)域名开头部分,使用相同的路有规则;
Route::domain(['news', 'blog', 'live'], function () {
Route::rule('details/:id', 'Address/details');
});
- 可以作为方法,进行二级(子)域名开头部分的检测,或完整域名检测;
Route::rule('details/:id', 'Address/details')->domain('tp6');
Route::rule('details/:id', 'Address/details')->domain('tp6.1997sty.com');
- 路由域名也支持:
ext
,pattern
,append
等路由参数方法的操作;
跨域请求
- 当不同域名进行跨域请求的时候,由于浏览器的安全限制,会被拦截;
- 所以,为了解除这个限制,我们通过路由
allowCrossDomain()
来实现;
Route::rule('details/:id', 'Address/details')->allowCrossDomain();
- 实现跨域比如没有实现的header头文件多了几条开头为Access的信息;
- 此时,这个页面,就可以支持跨域请求的操纵了;
- 我们创建一个不同端口号或不同域名的ajax按钮,点击获取这个路由页面信息;
- 如果,没有开启跨域请求,则会报错:
已拦截跨源请求:同源策略禁止读取位于 http://localhost:8000/details/5.html 的远程资源.(原因:CORS 头缺少 'Access-Control-Allow-Origin')
- 开启后,即正常获取得到的数据;
- 如果你想限制跨域请求的域名,则可以增加一条参数,仅允许访问该参数指定的域名;
Route::rule('col/:id', 'Collect/read')->allowCrossDomain(['Access-Control-Allow-Origin' => 'http://tp6.1997sty.com:8000']);
路由的分组和MISS
路由分组
- 路由分组,即将相同前缀的路由合并分组,这样可以简化路由定义,提高匹配效率;
- 使用
group()
方法,来进行分组路由的注册;
Route::group('address', function () {
Route::rule(':id', 'Address/details');
Route::rule(':name', 'Address/search');
})->ext('html')->pattern(['id'=>'\d+', 'name'=>'\w+']);
- 也可以省去第一参数,让分组路由更灵活一些;
Route::group(function () {
Route::rule('ds/:id', 'Address/details');
Route::rule('sr/:name', 'Address/search');
})->ext('html')->pattern(['id'=>'\d+', 'name'=>'\w+']);
- 使用
prefix()
方法,可以省略掉分组地址里的控制器;
Route::group('address', function () {
Route::rule(':id', 'details');
Route::rule(':name', 'search');
})->ext('html')->prefix('Address/')->pattern(['id'=>'\d+', 'name'=>'\w+']);
- 使用
append()
方法,可以额外传入参数;
Route::group()...->append(['status'=>1]);
- 路由规则(主要是分组和域名路由)定义的文件,加载时会解析消耗较多的资源;
- 尤其是规则特别庞大的时候,延迟解析开启让你只有在匹配的时候才会注册解析;
- 我们在
route.php
中开启延迟解析,多复制几组规则,然后来查看内存占用;
'url_lazy_route' => true,
MISS 路由
- 全局MISS,类似开启强制路由功能,匹配不到相应规则时自动跳转到MISS;
Route::miss('Index/miss');
- 分组MISS,可以在分组中使用
miss
方法,当不满足匹配规则时跳转到这里;
Route::miss('miss');
资源路由
资源路由
- 资源路由,采用固定的常用方法来实现简化URL的功能;
Route::resource('ads', 'Address');
- 系统提供了一个命令,方便开发者快速生成一个资源控制器;
php think make:controller Blog
- 从生成的多个方法,包含了显示,增删改查等多个操作方法;
- 在路由定义文件下创建一个资源路由,资源名称可自定义;
Route::resource('blog', 'Blog');
- 这里的
blog
表示资源规则名,Blog
表示路由的访问路径; - 资源路由注册成功后,会自动提供以下方法,无须手动注册;
- GET 访问模式下:
index(blog)
,create(blog/create)
,read(blog/:id)
,edit(blog/:id/edit)
- POST 访问模式下:
save(blog)
; - PUT 方式模式下:
update(blog/:id)
; - DELETE 方式模式下:
delete(blog/:id)
;
http://localhost:8000/blog/ (index)
http://localhost:8000/blog/5 (read)
http://localhost:8000/blog/5/edit (edit)
- 对于POST,是新增,一般是表单的POST提交,而PUT和DELETE用AJAX访问;
- 将跨域提交那个例子修改成.ajax,其中type设置为DELETE即可访问到;
$.ajax({
type : "DELETE",
url : "http://localhost:8000/blog/10",
success : function (res) {
console.log(res);
}
});
- 默认的参数采用
id
名称,如果你想别的,比如:blog_id
,则:
->vars(['blog'=>'blog_id']); //相应的 delete($blog_id)
- 也可以通过
only()
方法限定系统提供的资源方法,比如:
->only(['index','save','create']);
- 还可以通过
except()
方法排除系统提供的资源方法,比如:
->except(['read','delete','update']);
- 使用
rest()
方法,更改系统给予的默认方法,1.请求方式;2.地址;3.操作;
Route::rest('create', ['GET', '/:id/add', 'add']);
//批量
Route::rest([
'save' => ['POST', '', 'store'],
'update' => ['PUT', '/:id', 'save'],
'delete' => ['DELETE', '/:id', 'destory'],
]);
- 使用嵌套资源路由,可以让上级资源对下级资源进行操作,创建
Comment
资源;
class Comment
{
public function read($id, $blog_id)
{
return 'Comment id:'.$id.',Blog id:'.$blog_id;
}
public function edit($id, $blog_id)
{
return 'Comment id:'.$id.',Blog id:'.$blog_id;
}
}
- 使用嵌套资源路由,可以让上级资源对下级资源进行操作,创建
Comment
资源;
Route::resource('blog.comment', 'Comment');
- 资源嵌套生成的路由规则如下:
http://localhost:8000/blog/:blog_id/comment/:id
http://localhost:8000/blog/:blog_id/comment/:id/edit
- 嵌套资源生成的上级资源默认
id
为:blog_id
,可以通过vars
更改;
Route::resource('blog.comment', 'Comment')->vars(['blog'=>'blogid']);
注解路由和URL生成
注解路由
- 路由的注解方式,并非系统默认支持,而是可选方案,需要额外安装扩展;
- 继续扩展安装,执行一下命令安装即可;
composer require topthink/think-annotation
- 安装好后,使用
use
引入相关类库;
use think\annotation\Route;
- 然后在控制器设置注解代码即可,可以使用PHPDOC生成一段,然后添加路由规则;
- 注意:这里必须使用双引号,单引号会直接报错;
/**
* @param $id
* @return string
* @route("details/:id");
*/
- 第二或以上参数,可以设置请求类型,比如要求是GET模式访问;
* @route("ds/:id", method="GET")
- 更多参数可实现更多功能(不需要考虑顺序),比如
ext
,https
等;
* @route("ds/:id", method="GET", ext="html", https=1) //布尔值 0,1 代替
- 注解模式也支持资源路由,先要
use
相关类库,然后声明;
use think\annotation\Route\Resource;
/**
* @Resource("blog") */
class Blog ...
- 注解模式也支持分组,先要
use
相关类库,然后声明;
use think\annotation\Route;
use think\annotation\route\Group;
* @Group("ads")
URL生成
- 首先,创建一个新的控制器:
Url.class
,创建一个路由方法和URL生成的方法; - 然后,路由这两个方法,具体如下:
Route::rule('ds', 'Url/index');
Route::rule('ds/:id', 'Url/details');
- 使用
Route::buildUrl('地址', [参数]...)
方式来获取路由的URL地址;
return Route::buildUrl('Url/details', ['id'=>5]);
- 注意:这里的地址和路由的定义是相辅相成的,如果没有定义,地址将会变化;
- 也可以给路由定义取一个别名,然后在生成URL的时候,直接使用这个别名调用;
Route::rule('ds/:id', 'Url/details')->name('u');
return Route::buildUrl('u', ['id'=>5]);
- 也可以直接使用路由地址生成URL,但这个方式并不需要和路由定义相匹配;
return Route::buildUrl('ds/5');
- 由于,我们默认在配置设置了后缀为
.html
,所以,生成的URL会自动加上;
return Route::buildUrl('ds/5')->suffix('shtml');
- 如果,你想添加完整域名路径,可以再添加
domain
方法;
return Route::buildUrl('ds/5')->domain(true);
return Route::buildUrl('ds/5')->domain('news');
return Route::buildUrl('ds/5')->domain('news.abc.com');
return Route::buildUrl('ds/5@news.abc.com');
- 也可以直接使用助手函数
url()
来代替Route::buildUrl()
;
return url('ds/5');
最后一次更新于2020-07-31 16:47
0 条评论