## 7. 路由分组 >[info] ###提取路由静态部分,以动态变量区分不同路由地址,提高匹配效率。 ![](https://box.kancloud.cn/50ca2e1a9e854dbd2e93a0ff4e010ff6_729x267.png) * * * * * ### 7-1 路由分组的基本概念: * 我们先看一下典型的路由注册文件:route.php ~~~ <?php use think\Route; //导入路由类 Route::get( 'staff/:id$', //路由表达式:静态地址/:动态变量 'index/Index/getStaff', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 ['id'=>'\d{4}'] //变量规则:\d{4} 必须是数字0-9,且必须是4位 ); Route::get( 'staff/:salaryMin/:salaryMax$', //路由表达式:静态地址/:动态变量 'index/Index/getSalary', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 [ 'salaryMin'=>'\d{3,5}', //变量规则:必须是纯数字0-9,且必须在3到5位之间 'salaryMax'=>'\d{3,5}' //变量规则:必须是纯数字0-9,且必须在3到5位之间 ] ); Route::get( 'staff/:ageMin/:ageMax$', //路由表达式:静态地址/:动态变量 'index/Index/getAge', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 [ 'ageMin'=>'\d{2}', //变量规则:必须是纯数字0-9,且必须是2位数 'ageMax'=>'\d{2}' //变量规则:必须是纯数字0-9,且必须是2位数 ] ); ~~~ > 发现规律了吗?这3个路由规则中,路由表达式的静态地址部分是完全相同的,而动态变量部分各不相同。那我们能不能把相同部分提取出来,来简化我们的路由规则呢?当然可以! * * * * * ## 准备工作: >[success] ### 1. 我们先创建一张员工信息表(tp5_staff), 进行查询操作: 1. 根据主键获取指定记录; 2. 根据工资区间,获取相关员工信息; 3. 根据年龄区间,获取相关员工信息; * 表中信息如下: ![](https://box.kancloud.cn/7599f4a144f919aff051988318a6cb42_694x309.png) > 数据表的创建与操作请参考课程:http://www.kancloud.cn/ldkt/tp5_db * * * * * >[success] ###2. 为了便于演示,我们先创建好控制器:Index.php ~~~ class Index { public function getStaff($id) { //根据主键查询指定记录(闭包实现) $data = Staff::get(function ($query) use ($id) { $query -> field(['id'=>'编号','name'=>'姓名','age'=>'年龄','salary'=>'工资']) -> where(['id'=>['=',$id]]); }); //输出该模板对象的原始记录(二维数组) dump($data->getData()); } public function getSalary($salaryMin,$salaryMax) { //根据工资金额区间,查询符合条件的记录 $data=Staff::all(function($query) use ($salaryMin,$salaryMax) { $query->field(['id'=>'编号','name'=>'姓名','age'=>'工资']) -> where(['salary'=>['between',[$salaryMin,$salaryMax]]]); }); //循环输出该模型对象[数组]的原始记录(二维数组) foreach ($data as $list) { dump($list -> getData()); } } public function getAge($ageMin,$ageMax) { //根据年龄区间,查询符合条件的记录 $data=Staff::all(function($query) use ($ageMin,$ageMax) { $query->field(['id'=>'编号','name'=>'姓名','age'=>'年龄']) -> where(['age'=>['between',[$ageMin,$ageMax]]]); }); //循环输出该模型对象[数组]的原始记录(二维数组) foreach ($data as $list) { dump($list -> getData()); } } } ~~~ * 控制器代码的简单介绍: 1. `getStaff()` 方法根据数据表主键返回一条记录; 2. `getSalary()`方法根据路由规则给出的salary字段值区间,获取符合条件的数据集合; 3. `getAge()`方法与上面类似,根据URL路由中给出的age字段值区间获取符合条件数据集合; 4. 获取数据,我们全部采用模型类的静态方法实现,查询条件全部采用闭包实现。 >[warning] ###静态方法+闭包查询,是执行效率最高的黄金组合,强烈推荐! * * * * * >[success] ### 3.3 创建模型Staff.php ~~~ <?php namespace app\model; use think\Model; //导入模型类 class Staff extends Model { //此例仅仅是用到了模型的内置方法,此处留空即可 } ~~~ ### 7-1: 动态路由分组实例演示 >[info] ### 动态分组路由注册:Route::group( ) #### 第一步:创建路由配置文件:/application/route.php ~~~ <?php use think\Route; //导入路由类 Route::group('staff', //分组标识符:staff [ ':id$'=>[ 'index/Index/getStaff', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 ['id'=>'\d{4}'] //变量规则:\d{4} 必须是数字0-9,且必须是4位 ], ':salaryMin/:salaryMax$'=>[ 'index/Index/getSalary', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 [ 'salaryMin'=>'\d{3,5}', //变量规则:必须是纯数字0-9,且必须在3到5位之间 'salaryMax'=>'\d{3,5}' //变量规则:必须是纯数字0-9,且必须在3到5位之间 ] ], ':ageMin/:ageMax$'=>[ 'index/Index/getAge', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 [ 'ageMin'=>'\d{2}', //变量规则:必须是纯数字0-9,且必须是2位数 'ageMax'=>'\d{2}' //变量规则:必须是纯数字0-9,且必须是2位数 ] ] ]); ~~~ * * * * * ### 第二步:测试动态路由分组 >[success] ####1. 查询主键等于1016的员工信息 * 浏览器中输入:http://tp5.com/staff/1016.html > 根据变量规则,参数是4位纯数字,将自动调用:index/Index/getStaff操作,并传入主键1016给参数$id; * 运行结果: ~~~ array(4) { ["编号"] => int(1016) ["姓名"] => string(6) "马云" ["年龄"] => int(10) ["工资"] => float(3900) } ~~~ * 生成的SQL语句: ~~~ SELECT `id` AS `编号`,`name` AS `姓名`,`age` AS `年龄`,`salary` AS `工资` FROM `tp5_staff` WHERE `id` = 1016 LIMIT 1; ~~~ >[success] ####2. 查询工资在5000元到6000元之间的员工信息 * 浏览器中输入:http://tp5.com/staff/5000/6000.html >根据变量规则,参数数量是2个,且每个参数是3位以上5位以下纯数字,将自动定位到:index/Index/getSalary操作,并传入二个值给参数:$salaryMin和$salaryMax; * 运行结果如下(有3条满足条件): ~~~ array(3) { ["编号"] => int(1008) ["姓名"] => string(6) "林冲" ["工资"] => int(45) } array(3) { ["编号"] => int(1006) ["姓名"] => string(6) "杨康" ["工资"] => int(40) } array(3) { ["编号"] => int(1011) ["姓名"] => string(6) "宋江" ["工资"] => int(58) } ~~~ * 对应生成的SQL语句: ~~~ SELECT `id` AS `编号`,`name` AS `姓名`,`age` AS `工资` FROM `tp5_staff` WHERE `salary` BETWEEN 5000 AND 6000; ~~~ >[success] ####3. 查询年龄在30岁到40岁之间的员工信息 * 浏览器中输入:http://tp5.com/staff/30/40.html >根据变量规则,参数数量是2个,且每个参数是2纯数字,将自动定位到:index/Index/getAge操作,并传入二个值给参数:$ageMin和$ageMax; * 查询结果如下(有3条符合条件): ~~~ array(3) { ["编号"] => int(1006) ["姓名"] => string(6) "杨康" ["年龄"] => int(40) } array(3) { ["编号"] => int(1009) ["姓名"] => string(6) "武松" ["年龄"] => int(35) } array(3) { ["编号"] => int(1010) ["姓名"] => string(9) "西门庆" ["年龄"] => int(30) } ~~~ * 对应的SQL语句: ~~~ SELECT `id` AS `编号`,`name` AS `姓名`,`age` AS `年龄` FROM `tp5_staff` WHERE `age` BETWEEN 30 AND 40; ~~~ ### 7-2:静态路由分组 >[info] ### 非常简单,就是以[数组]方式创建的路由分组! * 修改路由配置文件:/application/route.php ~~~ <?php //创建静态路由分组 return [ '[staff]'=>[ //路由分组标识符, 注意必须加方括号:[ ] ':id$'=>[ 'index/Index/getStaff', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 ['id'=>'\d{4}'] //变量规则:\d{4} 必须是数字0-9,且必须是4位 ], ':salaryMin/:salaryMax$'=>[ 'index/Index/getSalary', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 [ 'salaryMin'=>'\d{3,5}', //变量规则:必须是纯数字0-9,且必须在3到5位之间 'salaryMax'=>'\d{3,5}' //变量规则:必须是纯数字0-9,且必须在3到5位之间 ] ], ':ageMin/:ageMax$'=>[ 'index/Index/getAge', //路由地址:路由到模块/控制器/操作 ['ext'=>'html'], //路由参数:URL必须以html结尾 [ 'ageMin'=>'\d{2}', //变量规则:必须是纯数字0-9,且必须是2位数 'ageMax'=>'\d{2}' //变量规则:必须是纯数字0-9,且必须是2位数 ] ] ] ]; ~~~ * 静态路由分组的测试,与动态分组完全一致,此处不再赘述! * * * * * ## 总结: >[success] ###路由分组是一项非常实用的技能,尤其适合于多路由,无论是静态还是动态设置,其效率都是一样的,究竟用哪个,视个人喜好,我用动态路由比较多。