# **路由:**
ThinkPHP5.0的路由规则定义是从根目录开始,而不是基于模块名的。
application/route.php注册 然后访问变成`http://serverName/new/5`
~~~
use think\Route;
// 注册路由到index模块的News控制器的read操作
Route::rule('new/:id','index/News/read');
~~~
## **参数配置:**
```
// 是否开启路由
'url_route_on' => true,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 路由使用完整匹配
'route_complete_match' => false,
// 是否强制使用路由 为true的话必须要为每个url配置路由才能访问哦 所以才开发阶段可以false 这样原url和路由url都可以访问到
'url_route_must' => false,
```
路由模式:**普通**、**强制**和**混合**模式
**1、普通模式:**
~~~
//配置文件 关闭路由,完全使用默认的PATH_INFO方式URL
'url_route_on' => false,
~~~
路由关闭后,不会解析任何路由规则,采用默认的`PATH_INFO`模式访问URL:
~~~
http://serverName/index.php/module/controller/action/param/value/...
~~~
关闭路由后的普通模式任然可以通过操作方法的 **[参数绑定](https://www.cnblogs.com/lichihua/p/10405130.html)**、控制器和空操作等特性实现url地址的简化
可以设置`url_param_type`配置参数来改变pathinfo模式下面的参数获取方式,默认是按名称成对解析,支持按照顺序解析变量,只需要更改为:
~~~
// 按照顺序解析变量
'url_param_type' => 1,
~~~
**2、强制模式:**
~~~
//配置文件如下配置
'url_route_on' => true,
'url_route_must' => true,
//这种方式下面必须严格给每一个访问地址定义路由规则(包括首页),否则将抛出异常。
//首页的路由规则采用/定义即可,例如下面把网站首页路由输出Hello,world!
Route::get('/',function(){
return 'Hello,world!';
});
~~~
**3、混合模式:**
~~~
//开启路由,并使用路由定义+默认PATH_INFO方式的混合
//配置如下
'url_route_on' => true,
'url_route_must'=> false,
//该方式下面,只需要对需要定义路由规则的访问地址定义路由规则,其它的仍然按照第一种普通模式的PATH_INFO模式访问URL
~~~
注册方式:**动态注册**和**路由配置**两种方式
>[danger]由于检测机制问题,**动态注册的性能比路由配置要高一些**,尤其是多种请求类型混合定义的时候。
**1、动态注册:**
路由定义采用`\think\Route`类的`rule`方法注册,通常是在应用的路由配置文件`application/route.php`进行注册,格式是
>[info]### **Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)');**
请求类型不指定的话默认为任何请求类型包含(GET、POST、PUT、DELETE、*表示任何其他请求)
~~~
单个注册:
Route::rule('路由规则表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)');
例子:
Route::rule(
'theme/:id/[:name]',
'home/Goods/theme',
'GET',
//路由参数
[
'method'=>'POST|GET|PUT',//请求类型检测
'ext'=>'shtml|html|php',//检测是shtml|html|php这三个后缀的请求就通过
'deny_ext'=>'jpg|png|gif',//URL禁止后缀检测,这里禁止检测jpg|png|gif者三个后缀
'domain'=>'news.thinkphp.cn',//子域名检测则直接news就行'domain'=>'news']
'https'=>true,//检测是否https请求
'before_behavior'=>'\app\index\behavior\UserCheck',//前置行为(检测)
'after_behavior'=>'\app\index\behavior\ReadInfo',//后置行为(执行)
'callback'=>'my_check_fun',//自定义检测方法
'merge_extra_vars'=>true,//合并额外参数
'cache'=>3600,//请求缓存V5.0.1+
'bind_model'=>['User','name'],//绑定模型V5.0.1+
'param_depr'=>'',//路由参数分隔符V5.0.2+
'ajax'=>true,//V5.0.2+
'pjax'=>true,//V5.0.2+
],
['name'=>'\w+','id'=>'\d+']
);
批量注册:
Route::rule(
[
'路由规则表达式1'=>'路由地址和参数',
'路由规则表达式2'=>['路由地址和参数','路由参数(数组)','变量规则(数组)']
],
'',
'请求类型',
'路由参数(数组)',
'变量规则'
);
//批量注册例子
Route::rule(
[
'new/:id' => 'News/read',
'blog/:id' => ['Blog/update',['ext'=>'shtml'],['id'=>'\d{4}']
],
],
'',
'GET',
['ext'=>'html'],
['id'=>'\d+']
);
~~~
### **路由规则表达式**
通常包含静态地址和动态地址,或者两种地址的结合,例如下面都属于有效的规则表达式:
~~~
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'); // 全动态地址
//当控制器文件不再controler文件夹下而是在controller子文件夹下时我们定义路由地址格式为\[子文件名. 控制器名\]
//controller/v1/Banner.php 访问为:http://www.localhost/api/v1/banner/1
Route::get("api/v1/banner/:id","api/v1.Banner/getBanner");
//下面是动态调用(如不同版本)
Route::get("api/:version/banner/:id","api/:version.Banner/getBanner");
//当前新品
Route::get("api/:version/product/recent","api/:version.Product/getRecent");
~~~
### **路由地址:**
~~~
1、路由到模块/控制器/操作:'[模块/控制器/]操作?额外参数1=值1&额外参数2=值2...'
// 路由到默认或者用define('BIND_MODULE','index');绑定的模块
'blog/:id'=>'blog/read',
// 路由到admin模块
'blog/:id'=>'admin/blog/read',
//支持多级控制器,路由到index/controller/group/Blog
'blog/:id'=>'index/group.blog/read',
//支持路由到动态的模块、控制器或者操作
// action变量的值作为操作方法传入
':action/blog/:id' => 'index/blog/:action'
// 变量传入index模块的控制器和操作方法
':c/:a'=> 'index/:c/:a'
//额外参数`status`和`app_id`参数都是URL里面不存在的,属于隐式传值,当然并不一定需要用到,只是在需要的时候可以使用。
'blog/:id'=>'blog/read?status=1&app_id=5',
2、路由到操作方法: @[模块/控制器/]操作
//区别是直接执行某个控制器类的方法,而不需要去解析**模块/控制器/操作**这些,同时也不会去初始化模块
//前者走模块初始化的 这个是直接调用控制器类 性能好点
//直接执行Loader::action('index/blog/read');相当于直接调用 \app\\index\controller\blog类的read方法。
'blog/:id'=>'@index/blog/read',
3、路由到类的方法
动态:\完整的类命名空间\类名@方法名
静态:\完整的类命名空间\类名::方法名
// \app\index\service\Blog类的read方法
'blog/:id'=>'\app\index\service\Blog@read',
'blog/:id'=>'\app\index\service\Blog::read',//这个read是静态方法
'blog/:id'=>'\app\index\service\Blog::read?status=1',//这个read是静态方法
4、路由到重定向地址:'外部地址'(默认301重定向) 或者 \['外部地址','重定向代码'\]
必须以“/”或者http开头
'blog/:id'=>'/blog/read/id/:id'
// 表示当前网站(可能是http://thinkphp.cn )的 blog/123地址
// 会直接重定向到http://blog.thinkphp.cn/read/123。
'blog/:id'=>'http://blog.thinkphp.cn/read/:id'
~~~
**路由地址参数可选定义**
变量用 [ ] 包含起来后就表示该变量是路由匹配的可选变量
~~~
Route::get('blog/:year/[:month]','Blog/archive');
下面的URL访问地址都可以被正确的路由匹配:
http://serverName/index.php/blog/2015
http://serverName/index.php/blog/2015/12
~~~
### **路由参数**
路由参数以数组的形式出现,他们都是可选的,根据实际情况组合
```
'method'=>'POST|GET|PUT',//请求类型检测
'ext'=>'shtml|html|php',//检测是shtml|html|php这三个后缀的请求就通过
'deny_ext'=>'jpg|png|gif',//URL禁止后缀检测,这里禁止检测jpg|png|gif者三个后缀
'domain'=>'news.thinkphp.cn',//子域名检测则直接news就行'domain'=>'news']
'https'=>true,//检测是否https请求
'before_behavior'=>'\app\index\behavior\UserCheck',//前置行为(检测)
'after_behavior'=>'\app\index\behavior\ReadInfo',//后置行为(执行)
'callback'=>'my_check_fun',//自定义检测方法
'merge_extra_vars'=>true,//合并额外参数
'cache'=>3600,//请求缓存V5.0.1+
'bind_model'=>['User','name'],//绑定模型V5.0.1+
'param_depr'=>'',//路由参数分隔符V5.0.2+
'ajax'=>true,//V5.0.2+
'pjax'=>true,//V5.0.2+
```
### **变量规则**
###
设置全局变量规则,全部路由有效:
~~~
全局变量规则,作用于全部路由
// 设置name变量规则(采用正则定义)
Route::pattern('name','\w+');
// 支持批量添加
Route::pattern([
'name' => '\w+',
'id' => '\d+',
]);
局部变量规则,仅在当前路由有效
// 定义GET请求路由规则 并设置name变量规则
Route::get('new/:name','News/read',[],['name'=>'\w+']);
~~~
### **请求类型**
默认支持所有的请求类型,可单独设置,多个用|分隔
~~~
//如果要定义get和post请求支持的路由规则,也可以用:
Route::rule('new/:id','News/read','GET|POST');
~~~
不同的请求类型定义路由规则的简化方法:请求类型参数必须大写
~~~
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'); // 所有请求都支持的路由规则
~~~
## **路由标志:设置一个唯一的用于url生成的字符**
~~~
// 注册路由到index模块的News控制器的read操作
Route::name('new_read')->rule('new/:id','index/News/read');
//生成路由地址的时候就可以使用
url('new_read',['id'=>10]);
//如果不定义路由标识的话,使用下面的方式生成
url('index/News/read',['id'=>10]);
V5.1.6+ 版本开始,路由标识的用法调整,原来的用法:
// 注册路由到index模块的News控制器的read操作
Route::name('new_read')->rule('new/:id','index/News/read');
需要改为:
// 注册路由到index模块的News控制器的read操作
Route::rule('new/:id','index/News/read')->name('new_read');
因为后者更符合语义。
~~~
## **路由别名:Route::alias('别名','模型/控制器');**
~~~
use think\Route;
Route::alias('home','index/index');
Route::alias('admin','admin/index');
或者:
return [
'__alias__' => [
'home' => 'index/index',
'admin'=> 'admin/index'
],
];
~~~
## **资源路由**
~~~
//注册资源路由(资源路由会自动注册7个路由规则分别对应下面新建的这几个方法)
//动态注册
Route::resource('user','index/user');
//或者路由配置
return [
// 定义资源路由
'__rest__'=>[
// 指向index模块的User控制器
'user'=>'index/user',
],
// 定义普通路由
'hello/:id'=>'index/hello',
];
//在指向index模块的User控制器新建index()、create($id)、save、read($id)、eidit($id)、update($id)、delete($id)方法
URL访问:
index:访问用户列表【GET】index方法可省略
http://serverName/user/
create:创建用户页面【GET】
http://serverName/user/create
save:创建用户【POST】
http://serverName/user/
read:获取单个用户信息【GET】
http://serverName/user/128
edit:获取编辑数据(更新页面)【GET】
http://serverName/user/128/edit
update:更新单个用户(实际执行编辑更新)【PUT】
http://serverName/user/128
delete:删除单个用户【DELETE】
http://serverName/user/128
~~~
将参数$id定义为$blog_id
~~~
Route::resource('user','index/user',['var'=>['user'=>'user_id']]);
对应方法变为
index()、create($user_id)、save、read($user_id)、eidit($user_id)、update($user_id)、delete($user_id)方法
~~~
也可以在定义资源路由的时候限定执行的方法(标识),例如:
~~~
// 只允许index read edit update 四个操作
Route::resource('user','index/user',['only'=>['index','read','edit','update']]);
// 排除index和delete操作
Route::resource('user','index/user',['except'=>['index','delete']]);
~~~
资源路由的标识不可更改,但生成的路由规则和对应操作方法可以修改。
数组第一个参数:请求类型
数组第二个参数:请求规则
数组第三个参数:路由标识对应的控制器方法请求
~~~
// 修改之前看下默认的REST路由操作方法定义
private static $rest = [
'index' => ['get', '', 'index'],
'create' => ['get', '/create', 'create'],
'edit' => ['get', '/:id/edit', 'edit'],
'read' => ['get', '/:id', 'read'],
'save' => ['post', '', 'save'],
'update' => ['put', '/:id', 'update'],
'delete' => ['delete', '/:id', 'delete'],
];
Route::rest('create',['GET', '/add','add']);
//支持批量更改
Route::rest([
'index'=>['GET','','front'],
'create'=>['GET', '/add','add']
'save' => ['POST', '', 'store'],
'update' => ['PUT', '/:id', 'save'],
'delete' => ['DELETE', '/:id', 'destory'],
]);
URL访问:
index:访问用户列表【GET】访问的是front方法而不是index方法
http://serverName/user
create:创建用户页面【GET】
http://serverName/user/add
save:创建用户【POST】访问的是store方法了而不是默认的save方法
http://serverName/user/
read:获取单个用户信息【GET】
http://serverName/user/128
edit:获取编辑数据(更新页面)【GET】
http://serverName/user/128/edit
update:更新单个用户(实际执行编辑更新)【PUT】访问的是save方法而不是update方法
http://serverName/user/128
delete:删除单个用户【DELETE】访问的是destory方法而不是delete方法
http://serverName/user/128
~~~
### 资源嵌套
支持资源路由的嵌套,例如:
~~~
Route::resource('blog.comment','index/comment');
~~~
就可以访问如下地址:
~~~
http://serverName/blog/128/comment/32
http://serverName/blog/128/comment/32/edit
~~~
生成的路由规则分别是:
~~~
blog/:blog_id/comment/:id
blog/:blog_id/comment/:id/edit
~~~
Comment控制器对应的操作方法如下:
~~~
namespace app\index\controller;
class Comment{
public function edit($id,$blog_id){
}
}
~~~
edit方法中的参数顺序可以随意,但参数名称必须满足定义要求。
如果需要改变其中的变量名,可以使用:
~~~
// 更改嵌套资源路由的blog资源的资源变量名为blogId
Route::resource('blog.comment','index/comment',['var'=>['blog'=>'blogId']]);
~~~
Comment控制器对应的操作方法改变为:
~~~
namespace app\index\controller;
class Comment{
public function edit($id,$blogId)
{
}
}
~~~
`Route::resource('blog','index/blog');`路由规则:
| 标识 | 请求类型 | 生成路由规则 | 对应操作方法(默认) | url地址|
| --- | --- | --- | --- | --- |
| index | GET | `blog` | index |http://serverName/blog|
| create | GET | `blog/create` | create($id) | http://serverName/blog/create|
| save | POST | `blog` | save | http://serverName/blog/|
| read | GET | `blog/:id` | read($id) | http://serverName/blog/128|
| edit | GET | `blog/:id/edit` | edit($id) | http://serverName/blog/128/edit|
| update | PUT | `blog/:id` | update($id) |http://serverName/blog/128|
| delete | DELETE | `blog/:id` | delete($id) |http://serverName/blog/128|
资源路由的嵌套`Route::resource('blog.comment','index/comment'`
会对应index模块的comment控制器
路由规则
| 标识 | 请求类型 | 生成路由规则 | 对应操作方法(默认) |url地址|
| --- | --- | --- | --- | --- |
| index | GET | `blog` | index |http://serverName/blog|
| create | GET | `blog/create` | create($id) | http://serverName/blog/create|
| save | POST | `blog` | save | http://serverName/blog/|
| read | GET | blog/:blog_id/comment/:id | read($id) | http://serverName/blog/128|
| edit | GET | blog/:blog_id/comment/:id/edit | edit($id,$blog_id) | http://serverName/blog/128/comment/32/edit|
| update | PUT | blog/:blog_id/comment/:id | update($id) |http://serverName/blog/128|
| delete | DELETE | blog/:blog_id/comment/:id | delete($id) |http://serverName/blog/128|
参数的顺序随便
同理也可以更改参数变量名
~~~
// 更改嵌套资源路由的blog资源的资源变量名为blogId
Route::resource('blog.comment','index/comment',['var'=>['blog'=>'blogId']]);
修改后方法变为:edit($id,$blogId)或edit($blogId, $id)
~~~
## **快捷路由**
```
//快捷路由 Route::controller('user','模块/控制器');
// 给User控制器设置快捷路由 控制器方法为 请求类型+方法名 如getInfo()与postInfo()
// get http://localhost/user/phone post http://localhost/user/info
Route::controller('user','index/User');
```
## **路由别名**
不支持变量类型和路由条件判断,单纯只是为了缩短URL地址 不推荐
~~~
//我们希望使用user可以访问Home模块的User控制器的所有操作 那么我么定义别名为
Route::alias('user','home/User');
//或者
return [
'__alias__' => [
'user' => 'home/User',
//'user' => ['home/User',['ext'=>'html']],
],
];
//路由别名可以指向任意一个有效的路由地址,例如下面指向一个类
// user 路由别名指向 User控制器类
Route::alias('user','\app\index\controller\User');
// user 别名路由到 index/user 控制器
Route::alias('user','index/user',[
'ext'=>'html',//设置路由条件
'allow'=>'index,read,edit,delete',//白名单
'except'=>'save,delete',//黑名单
'method'=>['index'=>'GET','save'=>'POST','delete'=>'DELETE'],//设置操作方法的请求类型
]);
~~~
## **路由分组**
~~~
Route::rule(
[
'blog/:id' => ['Blog/read', ['method' => 'get'], ['id' => '\d+']],
'blog/:name' => ['Blog/read', ['method' => 'post']],
],
);
//可以合并到一个blog分组
Route::rule(
[
'[blog]' => [
':id' => ['Blog/read', ['method' => 'get'], ['id' => '\d+']],
':name' => ['Blog/read', ['method' => 'post']],
],
],
);
~~~
也可以使用group方法进行分组
```
//路由分组 允许把相同前缀的路由定义合并分组
Route::group('blog',[
':id' => ['Blog/read', ['method' => 'get'], ['id' => '\d+']],
':name' => ['Blog/read', ['method' => 'post']],
],['method'=>'get','ext'=>'html']);
```
支持使用闭包方式注册路由分组,例如:
~~~
Route::group('blog',function(){
Route::any(':id','blog/read',[],['id'=>'\d+']);
Route::any(':name','blog/read',[],['name'=>'\w+']);
},['method'=>'get','ext'=>'html']);
~~~
如果仅仅是用于对一些路由规则设置一些公共的路由参数,也可以使用:
~~~
Route::group(['method'=>'get','ext'=>'html'],function(){
Route::any('blog/:id','blog/read',[],['id'=>'\d+']);
Route::any('blog/:name','blog/read',[],['name'=>'\w+']);
});
~~~
路由分组支持嵌套,例如:
~~~
Route::group(['method'=>'get','ext'=>'html'],function(){
Route::group('blog',function(){
Route::any('blog/:id','blog/read',[],['id'=>'\d+']);
Route::any('blog/:name','blog/read',[],['name'=>'\w+']);
}
});
~~~
## **MISS路由**
如果希望在没有匹配到所有的路由规则后执行一条设定的路由,可以使用`MISS`路由功能,只需要在路由配置文件中定义:
~~~
return [
'new/:id' => 'News/read',
'blog/:id' => ['Blog/update',['method' => 'post|put'], ['id' => '\d+']],
'__miss__' => 'public/miss',
];
~~~
或者使用`miss`方法注册路由
~~~
Route::miss('public/miss');
~~~
当没有匹配到所有的路由规则后,会路由到`public/miss`路由地址。
## 分组MISS路由
分组支持独立的`MISS`路由,例如如下定义:
~~~
return [
'[blog]' => [
'edit/:id' => ['Blog/edit',['method' => 'get'], ['id' => '\d+']],
':id' => ['Blog/read',['method' => 'get'], ['id' => '\d+']],
'__miss__' => 'blog/miss',
],
'new/:id' => 'News/read',
'__miss__' => 'public/miss',
];
~~~
如果使用`group`方法注册路由的话,可以使用下面的方式:
~~~
Route::group('blog',function(){
Route::rule(':id','blog/read',[],['id'=>'\d+']);
Route::rule(':name','blog/read',[],['name'=>'\w+']);
Route::miss('blog/miss');
},['method'=>'get','ext'=>'html']);
~~~
## **闭包定义**
我们可以使用闭包的方式定义一些特殊需求的路由,而不需要执行控制器的操作方法了,例如:
~~~
Route::get('hello',function(){
return 'hello,world!';
});
//参数传递,规则路由中定义的动态变量的名称 就是闭包函数中的参数名称,不分次序。
Route::get('hello/:name',function($name){
return 'Hello,'.$name;
});
因此,如果我们访问的URL地址是:http://serverName/hello/thinkphp
则浏览器输出的结果是:Hello,thinkphp
~~~
## **路由绑定**
### **绑定到模块/控制器/操作**
把当前的URL绑定到模块/控制器/操作,最多支持绑定到操作级别,例如在路由配置文件中添加:
~~~
// 绑定当前的URL到 index模块
Route::bind('index');
// 绑定当前的URL到 index模块的blog控制器
Route::bind('index/blog');
// 绑定当前的URL到 index模块的blog控制器的read操作
Route::bind('index/blog/read');
~~~
例子:
```
http://serverName/index/blog/read/id/5
如果定义了路由
Route::get('index/blog/:id','index/blog/read');
访问路径变为
http://serverName/index/blog/5
假如我们绑定到了index模块的blog控制器
Route::bind('index/blog');
那么访问URL就变成了
http://serverName/5
```
~~~
// 绑定命名空间
Route::bind('\app\index\controller','namespace');//通过http://serverName/blog/read/id/5就可以直接访问 \app\index\controller\Blog类的read方法。
// 绑定到类
Route::bind('\app\index\controller\Blog','class');//通过http://serverName/read/id/5就可以直接访问 \app\index\controller\Blog类的read方法。
//入口文件绑定
// 复制一份入口文件添加define('BIND_MODULE','admin'); 命名为demo.php 我们访问这个demo.php就访问的是admin模块
// 自动入口绑定
// 配置文件开启入口文件自动绑定模块 'auto_bind_module' => true,
//复制一份index.php 改名为demo.php 访问index.php是访问index模块 访问的demo.php则访问得是demo模块
~~~
## 模型绑定(`V5.0.1`)
路由规则和分组支持绑定模型数据,例如:
~~~
Route::rule('hello/:id','index/index/hello','GET',[
'ext' => 'html',
'bind_model' => [
'user' => '\app\index\model\User',
],
]);
~~~
会自动给当前路由绑定`id`为 当前路由变量值的`User`模型数据。
可以定义模型数据的查询条件,例如:
~~~
Route::rule('hello/:name/:id','index/index/hello','GET',[
'ext' => 'html',
'bind_model' => [
'user' => ['\app\index\model\User','id&name']
],
]);
~~~
表示查询`id`和`name`的值等于当前路由变量的模型数据。
也可以使用闭包来返回模型对象数据
~~~
Route::rule('hello/:id','index/index/hello','GET',[
'ext' => 'html',
'bind_model' => [
'user' => function($param){
$model = new \app\index\model\User;
return $model->where($param)->find();
}
],
]);
~~~
闭包函数的参数就是当前请求的URL变量信息。
在控制器中可以通过下面的代码或者使用依赖注入获取:
~~~
request()->user;
~~~
> 绑定的模型可以直接在控制器的架构方法或者操作方法中自动注入,具体可以参考请求章节的依赖注入。
## **域名路由**
全一点的例子
~~~
use think\Route;
// 注册路由到index模块的News控制器的read操作
Route::rule('show/:id','test/Index/index');//id必须
Route::rule('show/[:id]','test/Index/index');//id可选
Route::rule('new/:id','News/update','POST');//第三个参数为空则表示接受所有的请求类型的参数
//完全匹配
Route::rule('show/:id$','test/Index/index');//只有http://www.admindemo2.com/show/2才能访问而去掉$的话http://www.admindemo2.com/show/2/3/tom/...也能通过
//全局完全匹配(开启全局完全匹配后所有的都不用再加$)
//配置文件添加
//'route_complete_match' => true,//开启路由定义的全局完全匹配
//当开启全局完全匹配的时候,如果个别路由不需要使用完整匹配,可以添加路由参数覆盖定义:
//Route::rule('new/:id','News/read','GET|POST',['complete_match' => false]);
Route::get('routeget','test/Index/routeGet'); // 定义GET请求路由规则,同Route::rule('routeget','test/Index/routeGet','GET');//只接受get的请求
Route::get('routeget/:id','test/Index/routeGet'); // 同//Route::rule('routeget/:id','test/Index/routeGet','GET');//只接受get的请求
//注意: Route::get('routeget','test/Index/routeGet');与Route::get('routeget/:id','test/Index/routeGet');同时定义相当于Route::get('routeget/[:id]]','test/Index/routeGet');文档说明:注册多个路由规则后,系统会依次遍历注册过的满足请求类型的路由规则,一旦匹配到正确的路由规则后则开始调用控制器的操作方法,后续规则就不再检测 所以为了避免冲突最好将优先级高的放在最前面(比如单个设置的变量规则和路由规则放前面,全局的放在最后面)
Route::rule('routepost','test/Index/routePost','POST');//post的请求才能接受
Route::rule('routepostorget','test/Index/routePostOrGet','POST|GET');//只接受get和post请求,其他一律不接受
// 定义new路由命名标识
Route::rule(['name','routenameflag/:id'],'test/Index/routeNameFlag');
//http://www.admindemo2.com/routenmeflag/1
//{:url('name',['id'=>1])}
Route::rule(['name2','routenameflag2/'],'test/Index/routeNameFlag2');//第二个参数有没有/都无所谓
//http://www.admindemo2.com/routenmeflag2 or //http://www.admindemo2.com/routenmeflag2/
//{:url('name2')}
Route::rule(['name3','routenameflag3/[:id]'],'test/Index/routeNameFlag3');
//http://www.admindemo2.com/routenmeflag3 or //http://www.admindemo2.com/routenmeflag3/1
//{:url('name3')} or //{:url('name',['id'=>1])}
//批量注册:
Route::rule(['new/:id'=>'News/read','blog/:name'=>'Blog/detail']);
Route::get(['new/:id'=>'News/read','blog/:name'=>'Blog/detail']);
/*
Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)');
Route::rule(
[
'路由规则1'=>'路由地址和参数',
'路由规则2'=>['路由地址和参数','匹配参数(数组)','变量规则(数组)']
],
'',
'请求类型',
'匹配参数(数组)',
'变量规则'
);
*/
Route::rule(
[
'new/:id' => 'News/read',
'blog/:id' => ['Blog/update',['ext'=>'shtml'],['id'=>'\d{4}']],
':action/blog/:id' => 'index/blog/:action',// action变量的值作为操作方法传入
':c/:a'=> 'index/:c/:a',// 变量传入index模块的控制器和操作方法
],
'',
'GET',
['ext'=>'html'],
['id'=>'\d+']
);
//变量规则
//1、设置单个路由全局的变量规则
Route::rule('new/:tittle','News/update');
// 设置tittle变量规则(采用正则定义)
Route::pattern('name','\w+');
//2、批量设置路由全局规则
Route::rule('new/:tittle','News/update');
Route::rule('banner/:id','home/Goods/banner');
Route::pattern([
'tittle' => '\w+',
'id' => '\d+',
]);
//3、设置局部变量规则,仅在当前路由有效
Route::get('new/:name','News/read',[],['name'=>'\w+']);
//4、完整URL规则
Route::get('allurl/:catergory','test/Index/allUrl',[],['__url__'=>'allurl\/[A-Za-z0-9]{1,}$']);//id必须
//组合变量
//http://www.admindemo2.com/item-sb or http://www.admindemo2.com/item-sb555 or http://www.admindemo2.com/item-sb555a
/*Route::get('item-<name><id?>','test/Index/product',[],['name'=>'\w+','id'=>'\d+']);*/
// http://www.admindemo2.com/item-sb-555
Route::get('item-<name>-<id>','test/Index/product',[],['name'=>'\w+','id'=>'\d+']);
Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)');
例子:
Route::rule(
'theme/:id/[:name]',
'home/Goods/theme',//路由地址
'GET',
//路由参数
[
'method'=>'POST|GET|PUT',//请求类型检测
'ext'=>'shtml|html|php',//检测是shtml|html|php这三个后缀的请求就通过
'deny_ext'=>'jpg|png|gif',//URL禁止后缀检测,这里禁止检测jpg|png|gif者三个后缀
'domain'=>'news.thinkphp.cn',//子域名检测则直接news就行'domain'=>'news']
'https'=>true,//检测是否https请求
'before_behavior'=>'\app\index\behavior\UserCheck',//前置行为(检测)
'after_behavior'=>'\app\index\behavior\ReadInfo',//后置行为(执行)
'callback'=>'my_check_fun',//自定义检测方法
'merge_extra_vars'=>true,//合并额外参数
'cache'=>3600,//请求缓存V5.0.1+
'bind_model'=>['User','name'],//绑定模型V5.0.1+
'param_depr'=>'',//路由参数分隔符V5.0.2+
'ajax'=>true,//V5.0.2+
'pjax'=>true,//V5.0.2+
],
['name'=>'\w+','id'=>'\d+']
);
//路由地址
//1、额外参数:
Route::get('extraparams/:id','test/Index/extraParam?status=1&app_id=5');
// http://www.admindemo2.com/extraparams/2/3 访问
// Request::instance()->route()能获取到id、status、app_id
//2 路由到模块/控制器 [模块/控制器/]操作?参数1=值1&参数2=值2...
//2.1 路由到默认或者绑定模块
Route::rule('blog/:id','index/read');
//2.2 路由到index模块
Route::rule('blog/:id','test/index/read');
//2.3、路由到动态的模块、控制器或者操作
//http://www.admindemo2.com/moviemodel/index/1 访问到的是test/Index/movieModel()
Route::rule(':action/index/:id','test/Index/:action');
//http://www.admindemo2.com/moviemodel/lichihua/1 访问到的是test/Index/movieModel()
Route::rule(':action/lichihua/:id','test/Index/:action');
//4 路由到操作方法 @[模块/控制器/]操作
//'blog/:id'=>'@index/blog/read', 系统会直接执行 Loader::action('index/blog/read');
//这种方式看起来似乎和第一种是一样的,本质的区别是直接执行某个控制器类的方法,而不需要去解析 模块/控制器/操作这些,同时也不会去初始化模块,视图的默认模板规则失效,所以这种情况下面,如果使用了视图模板渲染,则必须传入明确的参数
Route::get('test/:id','@test/Index/dongTest?status=1'); //??
//路由到类的方法 路由地址的格式为(动态方法):\类的命名空间\类名@方法名 或者(静态方法):\类的命名空间\类名::方法名
//可以支持执行任何类的方法,而不仅仅是执行控制器的操作方法
Route::rule('blog/:id','\app\index\service\Blog@read');//执行的是 \app\index\service\Blog类的read方法
Route::rule('blog/:id','\app\index\service\Blog::read');
//V5.0.4+版本开始,支持传入额外的参数作为方法的参数调用(用于参数绑定),例如:
Route::rule('blog/:id','\app\index\service\Blog::read?status=1');
//路由到重定向地址 以/或者http 开头
Route::rule('wolichihua/:id','/test/:id');
//http://www.admindemo2.com/wolichihua/1 访问到了est/Index/dongTest即上面定义的test/:id'
//资源路由
//在指向index模块的blog控制器新建index()、create($id)、save、read($id)、eidit($id)、update($id)、delete($id)方法然后动态注册(资源路由会自动注册7个路由规则分别对应这几个方法) 详情参考资源路由
Route::resource('blog','index/blog');
//或者路由配置
return [
// 定义资源路由
'__rest__'=>[
// 指向index模块的blog控制器
'blog'=>'index/blog',
],
// 定义普通路由
'hello/:id'=>'index/hello',
];
//快捷路由 Route::controller('user','模块/控制器');
// 给User控制器设置快捷路由 控制器方法为 请求类型+方法名 如getInfo()与postInfo()
// get http://localhost/user/phone post http://localhost/user/info
Route::controller('user','index/User');
//路由别名
//我们希望使用user可以访问Home模块的User控制器的所有操作 那么我么定义别名为
Route::alias('user','home/User');
//或者
return [
'__alias__' => [
'user' => 'home/User',
],
];
//路由别名可以指向任意一个有效的路由地址,例如下面指向一个类
// user 路由别名指向 User控制器类
Route::alias('user','\app\index\controller\User');
//路由分组 允许把相同前缀的路由定义合并分组
Route::group('blog',[
':id' => ['Blog/read', ['method' => 'get'], ['id' => '\d+']],
':name' => ['Blog/read', ['method' => 'post']],
],['ext'=>'html']);
//MISS路由:没有匹配到所有的路由规则后执行一条设定的路由,可以使用MISS路由功能, MISS路由配置后相当于开启了强制路由
//全局MISS路由
//Route::miss(); 放到路由的第一行才能生效,放到最后一行或者return里面不生效?????
Route::miss('public/miss');//当没有匹配到所有的路由规则后,会路由到 public/miss路由地址。
//分组MISS路由 分组支持独立的MISS路由
//
//
//闭包支持:
Route::get('hello/:name',function($name){
return 'Hello,'.$name;
});
//闭包还支持模板师视图
Route::get('/', function () {
return view('admin@home/index');
});
//路由绑定
// 绑定当前的URL到 index模块
Route::bind('index');
// 绑定当前的URL到 index模块的blog控制器
Route::bind('index/blog');//http://serverName/index/blog/read/id/5可以简化成http://serverName/read/id/5 ;如果定义了路由Route::get('index/blog/:id','index/blog/read');那么访问URL就变成了http://serverName/5
// 绑定当前的URL到 index模块的blog控制器的read操作
Route::bind('index/blog/read');
// 绑定命名空间
Route::bind('\app\index\controller','namespace');//通过http://serverName/blog/read/id/5就可以直接访问 \app\index\controller\Blog类的read方法。
// 绑定到类
Route::bind('\app\index\controller\Blog','class');//通过http://serverName/read/id/5就可以直接访问 \app\index\controller\Blog类的read方法。
//入口文件绑定
// 复制一份入口文件添加define('BIND_MODULE','admin'); 命名为demo.php 我们访问这个demo.php就访问的是admin模块
// 自动入口绑定
// 配置文件开启入口文件自动绑定模块 'auto_bind_module' => true,
//复制一份index.php 改名为demo.php 访问index.php是访问index模块 访问的demo.php则访问得是demo模块
//域名路由 省略
~~~
定义路由后参数的获取问题:
~~~
Route::get('hello/:id','index/test/hello');
以下三种是获取不到值的:
dump(request()->get());
dump(request()->get('id'));
dump(input('get.id'));
我们只有通过:下面这几个才能获取到
dump(request()->param());
dump(request()->param('id'));
dump(request()->route());
dump(request()->route('id'));
怎么才能让get获取到?
参数绑定和?后面的如:
public function hello($id){
dump(request()->get());
dump(input('get.'));
}
浏览器输入:域名/hello/10?name=123
array (size=2)
'name' => string '123' (length=3)
'id' => string '10' (length=2)
~~~
路由之后这些方法的controller和action的的值与实际的不同了
~~~
11.// 调用Request对象的path方法
12.{$Request.path}
13.// 调用Request对象的module方法
14.{$Request.module}
15.// 调用Request对象的controller方法
16.{$Request.controller}
17.// 调用Request对象的action方法
18.{$Request.action}
~~~
- 目录结构与基础
- 修改数据后页面无变化
- 防跨目录设置
- input
- 系统目录
- 自动生成的文件以及目录
- 类自动加载
- url生成
- 数据增删改查
- 增加数据
- 数据更新
- 数据删除
- 数据查询
- 架构
- 生命周期
- 入口文件
- URL访问规则
- 配置
- 默认惯例配置配置
- 初始应用配置
- 路由
- 域名路由
- URL生成
- 数据库操作
- 方法列表
- 连接数据库
- 分布式数据库
- 查询构造器
- 查询数据
- 添加数据
- 更新数据
- 删除数据
- 查询语法
- 聚合查询(统计)
- 时间查询
- 高级查询
- 视图查询
- 子查询
- 辅助查询之链式操作
- where
- table
- alias
- field
- order
- limit
- page
- group
- having
- join
- union
- distinct
- lock
- cache
- comment
- fetchSql
- force
- bind
- partition
- strict
- failException
- sequence(pgsql专用)
- 查询事件
- 事务操作
- 监听SQL
- 存储过程
- 数据集
- 控制器
- 跳转和重定向
- 空控制器和空操作
- 分层控制器
- Rest控制器
- 资源控制器
- 自动定位控制器
- tp3的增删改查
- 方法注入
- 模型
- 属性方法一览
- 类方法详解
- Model
- 调用model不存在的属性
- 调用model中不存在的方法
- 调用model中不存在的静态方法
- hasOne
- belongsTo
- hasMany {Relation}
- belongsToMany
- hasManyThrough
- morphMany
- morphOne
- morphTo
- ::hasWhere {Query}
- ::has
- relationCount
- data 【model】
- setInc {integer|true}
- setDec {integer|true}
- save {integer | false}
- saveAll {array}
- delete {integer}
- ::get 查询单条数据 {Model}
- ::all 查询多条数据{Model [ ]}
- ::create 新增单条数据 {Model}
- ::update 更新单条数据 {Model}
- ::destroy {integer}
- ::scope {Query}
- getAttr {mixed}
- xxx
- append
- appendRelationAttr
- hidden
- visible
- except
- readonly
- auto
- together
- allowField
- isUpdate
- validate
- toCollection
- toJson
- toArray
- 定义
- 新增
- 更新
- 查询
- 删除
- 聚合
- 获取器
- 修改器
- 时间戳
- 只读字段
- 软删除
- 类型转换
- 数据完成
- 查询范围
- 模型分层
- 数组访问和转换
- JSON序列化
- 事件
- 关联
- 一对一关联
- 主表一对一关联
- 从表一对一关联(相对关联)
- 一对多关联
- 主表定义一对多关联
- 从表定义一对多关联
- 远程一对多
- 多对多关联
- 多态关联
- 动态属性
- 关联预载入with()
- 关联统计
- N+1查询
- 聚合模型
- Model方法集合
- 表单验证
- 验证器
- 验证规则
- 错误信息
- 验证场景
- 控制器验证
- 模型验证
- 内置规则
- 静态调用
- 表单令牌
- Token身份令牌
- 视图
- 模版
- 变量输出
- 函数输出
- Request请求参数
- 模板注释及原样输出
- 三元运算
- 内置标签
- 模板继承
- 模板布局
- 日志
- 日志初始化
- 日志驱动
- 日志写入
- 独立日志
- 日志清空
- 写入授权
- 自定义日志
- 错误和调试
- 异常
- php系统异常及thinkphp5异常机制
- 异常处理
- 抛出异常
- 异常封装
- resful
- 404页面
- 调试模式
- Trace调试
- SQL调试
- 变量调试
- 性能调试
- 远程调试
- 安全
- 输入安全
- 数据库安全
- 上传安全
- 其它安全建议
- xss过滤
- 扩展
- 函数
- 类库
- 行为
- 驱动
- Composer包
- Time
- 数据库迁移工具
- Workerman
- MongoDb
- htmlpurifier XSS过滤
- 新浪SAE
- oauth2.0
- 命令行及生成文件
- 系统现成命令
- 创建类库文件
- 生成类库映射文件
- 生成路由缓存
- 清除缓存文件
- 生成配置缓存文件
- 生成数据表字段缓存
- 自定义命令行
- 开始
- 调用命令
- 杂项
- 助手函数
- URL重写
- 缓存
- 缓存总结
- Session
- Cookie
- 多语言
- 分页
- 上传
- 验证码
- 图像处理
- 文件处理
- 单元测试
- 自定义表单令牌