路由
基本优点:
- 让URL更规范以及优雅;
- 隐式传入额外请求参数;
- 统一拦截并进行权限检查等操作;
- 绑定请求数据;
- 使用请求缓存;
- 路由中间件支持
路由仅针对PATHINFO方式的URL有效,ThinkPHP5.1的路由定义更加对象化,并且默认开启路由(不能关闭),如果一个URL没有定义路由,则采用默认的PATH_INFO 模式访问URL
路由定义
route目录下的任何路由定义文件都是有效的,默认的路由定义文件是route.php(推荐定义在route.php中)
格式:
Route::rule('路由表达式','路由地址','请求类型');
实例:
// 注册路由到index模块的News控制器的read操作
Route::rule('new/:id','index/News/read');
我们可以访问
http://serverName/new/5
也可以访问
http://serverName/index/news/read/id/5
注
1、但是当我们开启强制路由后,就必须严格按照规定的路由表达式进行访问,否则会出错。
2、不指定请求类型式的话,默认为任何请求类型有效。但是指定请求类型后就必须使用对应的请求类型
3、开启强制路由后,会更加安全、规范
可以在config目录下的app.php中进行设置
// 是否强制使用路由
'url_route_must' => true,
常用请求
Route::get('new/:id','News/read'); // 定义GET请求路由规则
Route::post('new/:id','News/update'); // 定义POST请求路由规则
Route::put('new/:id','News/update'); // 定义PUT请求路由规则
Route::delete('new/:id','News/delete'); // 定义DELETE请求路由规则
Route::any('new/:id','News/read'); // 所有请求都支持的路由规则
路由表达式
路由表达式实际上就是定义路径的访问格式
1、路由表达式统一使字符串定义,采用规则定义的方式
2、规则表达式通常包含静态地址和动态地址,或者两种地址的结合
常见规则表达式
Route::rule('/', 'index'); // 首页访问路由
Route::rule('my', 'Member/myinfo'); // 静态地址路由
Route::rule('blog/:id', 'Blog/read'); // 静态地址和动态地址结合
Route::rule('new/:year/:month/:day', 'News/read'); // 静态地址和动态地址结合
Route::rule(':user/:blog_id', 'Blog/read'); // 全动态地址
路由参数
1、每个参数中以:开头的参数都表示动态变量,并且会自动绑定到操作方法的对应参数
2、参数也支持可选参数(这个参数可以有也可以没有,而且不会报错)
//普通
Route::rule('blog/:id', 'Blog/read');
//可选参数
Route::get('blog/:year/[:month]','Blog/archive');
注:
1、采用可选变量定义后,之前需要定义两个或者多个路由规则才能处理的情况可以合并为一个路由规则
2、可选参数只能放到路由规则的最后,如果在中间使用了可选参数的话,后面的变量都会变成可选参数。
路由匹配
规则匹配检测的时候默认只是对URL从头开始匹配,只要URL地址包含了定义的路由规则就会匹配成功,如果希望URL进行完全匹配,可以在路由表达式最后使用$符号,例如:
Route::get('new/:cate$', 'News/category');
这样定义后
http://serverName/index.php/new/info
会匹配成功,而
http://serverName/index.php/new/info/2
则不会匹配成功。
如果是采用
Route::get('new/:cate', 'News/category');
方式定义的话,则两种方式的URL访问都可以匹配成功。
如果需要全局进行URL完全匹配,可以在app.php中设置
// 开启路由完全匹配
'route_complete_match' => true,
建议开启全局路由完全匹配,防止在访问时往url中写入其它东西
闭包支持
我们可以使用闭包的方式定义一些特殊需求的路由,而不需要执行控制器的操作方法了
//无参
Route::get('hello', function () {
return 'hello,world!';
});
//传参
Route::get('hello/:name', function ($name) {
return 'Hello,' . $name;
});
//依赖注入
Route::rule('hello/:name', function (Request $request, $name) {
$method = $request->method();
return '[' . $method . '] Hello,' . $name;
});
//指定响应对象
Route::get('hello/:name', function (Response $response, $name) {
return $response
->data('Hello,' . $name)
->code(200)
->contentType('text/plain');
});
跨域请求
如果某个路由或者分组需要支持跨域请求,可以使用
Route::get('new/:id', 'News/read')->allowCrossDomain();
MISS路由
全局MISS路由
如果希望在没有匹配到所有的路由规则后执行一条设定的路由,可以注册一个单独的MISS路由
注:一旦设置了MISS路由,相当于开启了强制路由模式
miss路由就是当访问的地址不存在时,会给出一个统一的解决。这里的路由地址不存在分为两种情况:
1、路由地址确实不存在
2、路由地址存在,但是缺少参数(因为相当于开启了强制路由,路由地址必须严格符合要求)
实例
Route::miss('NotFound/miss');
对应的控制器
<?php
namespace app\index\controller;
class NotFound
{
public function miss()
{
return '404';
}
}
只要没有匹配到对应的路由地址,就会执行该控制器下的miss方法
快捷路由
快捷路由允许你快速给控制器注册路由,并且针对不同的请求类型可以设置方法前缀,例如:
// 给User控制器设置快捷路由
Route::controller('user','index/User');
//相当于以下两句
Route::get('user/login','index/user/getLogin');
Route::post('user/login','index/user/postLogin');
User控制器定义如下:
class User extends Container
{
public function getLogin()
{
//当通过get请求login时,渲染登录界面
return $this->view->fetch('login');
}
public function postLogin()
{
//当通过post请求login时,返回登录信息
$info = Request::param();
dump($info);
}
}
理解:
1、当一个控制器下的方法比较多时,采用快捷路由更加方便而且不容易出错
2、该实例虽然访问的地址相同,但是根据不同的访问方式(get或post方式)会调用不同的方法。如果不开启路由的话,这是无法实现的
路由别名
路由别名功能可以使用一条规则,批量定义一系列的路由规则。
例如,我们希望使用user可以访问index模块的User控制器的所有操作,可以使用:
// user 别名路由到 index/User 控制器
Route::alias('user','index/User');
路由别名与快捷路由有点相似,但是一条路径只能对应一个方法。
除了可以方便操作外还可以设置访问条件
// user 别名路由到 index/user 控制器
Route::alias('user', 'index/user', [
'ext' => 'html',
'except' => 'save,delete', //'allow' => 'index,save,delete',
'method' => ['index' => 'GET', 'save' => 'POST', 'delete' => 'DELETE'],
]);
- ext :指定可以访问的后缀
- exect:黑名单,指定那些方法不允许访问
- allow:白名单,指定那些方法允许访问
- metho:方式,指定哪一个方法必须使用某一种方式进行访问