简介
路由的作用就是让 URL地址更加的规范和优雅,或者说更加简洁。设置路由对 URL的检测、验证等一系列操作提供了极大的便利性。路由的配置文件在config/route.php中,定义文件在 route/app.php。route目录下的定义文件的文件名随机,都有效,或多个均有效果。路由是默认开启的,如果想要关闭路由,在 config/app.php配置:
// 是否启用路由
'with_route' => false,
前期准备:创建一个 Address控制器类,创建两个方法,具体如下:
class Address
{
public function index() {
return 'index';
}
public function details($id) {
return 'details目前调用的id:'.$id;
}
}
路由的定义
在没有定义路由规则的情况下,我们访问 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
或者使用如下方式,就是直接用 Route::get、Route::post等方式即可,无须第三参数,例如GET(get)、POST(post)、DELETE(delete)、PUT(put)、PATCH(patch)、*(any,任意请求方式)。
开始强制路由,需要在 route.php里面进行配置,然后配置首页路由:
'url_route_must' => true,
当我们设置了强制路由的时候,访问首页就会报错,必须强制设置首页路由:
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()方法,例如【1】将 details方法里的 id传值,严格限制必须只能是数字\d+:
Route::rule('details/:id', 'Address/details')
->pattern(['id'=>'\d+']);
【2】设置 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,ThinkPHP5!';
});
闭包支持也可以传递参数和动态规则:
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);
路由参数
设置路由的时候,可以设置相关方法进行,从而实施匹配检测和行为执行,例如【1】ext方法作用是检测 URL后缀,比如:我们强制所有 URL后缀为.html:
Route::rule('details/:id', 'address/details')->ext('html');
Route::rule('details/:id', 'address/details')->ext('html|shtml');
【2】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
]);
路由的域名和跨域请求
域名路由
准备工作——创建news.abc.com到localhost的映射(修改host文件)。如果想限定在 news.abc.com这个域名下才有效,通过域名路由闭包的形式:
Route::domain('news', function () {
Route::rule('details/:id', 'Address/details');
});
除了二级(子)域名的开头部分,也可以设置完整域名:
Route::domain('news.abc.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('news');
Route::rule('details/:id', 'Address/details')->domain('news.abc.com');
路由域名也支持:ext、pattern、append等路由参数方法的操作。
跨域请求
解决跨域问题,主要是通过路由 allowCrossDomain()来实现:
Route::rule('details/:id', 'Address/details')->allowCrossDomain();
实现跨域比如没有实现的 header头文件多了几条开头为 Access的信息。此时这个页面,就可以支持跨域请求的操纵了。我们创建一个不同端口号或不同域名的 ajax按钮,点击获取这个路由页面信息,如果,没有开启跨域请求,则会爆出提醒,开启后,即正常获取得到的数据。如果你想限制跨域请求的域名,则可以增加一条参数:
Route::rule('col/:id', 'Collect/read')
->allowCrossDomain([
'Access-Control-Allow-Origin' => 'http://news.abc.com:8000'
]
);
路由的分组和 MISS
路由分组
路由分组,即将相同前缀的路由合并分组,这样可以简化路由定义,提高匹配效率。使用 group()方法,来进行分组路由的注册。注意,group的第一个参数('address')可以省略。
Route::group('address', function () {
Route::rule(':id', 'Address/details');
Route::rule(':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('public/miss');
分组MISS,可以在分组中使用 miss方法,当不满足匹配规则时跳转到这里:
Route::miss('miss');