开启路由(config/app.php)
'with_route' => true,
开启强制路由(config.route.php)
'url_route_must' => false,
框架加载路由
在verdor/topthink/framework/src/think/Http.php
下面,可以看到,loadRoutes()
会加载你的应用下的route
目录下所有的PHP文件(所以框架不会管文件叫什么,我们自己知道怎么分类就行)
public function __construct(App $app)
{
$this->app = $app;
$this->routePath = $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR;
}
/**
* 加载路由
* @access protected
* @return void
*/
protected function loadRoutes(): void
{
// 加载路由定义
$routePath = $this->getRoutePath();
if (is_dir($routePath)) {
$files = glob($routePath . '*.php');
foreach ($files as $file) {
include $file;
}
}
$this->app->event->trigger(RouteLoaded::class);
}
并且,官方文档也说到
注册多个路由规则后,系统会依次遍历注册过的满足请求类型的路由规则,一旦匹配到正确的路由规则后则开始执行最终的调度方法,后续规则就不再检测。
配置路由
方式(1)
Route::rule('路由表达式', '路由地址', '请求类型');
//例如:
Route::rule('new/:id','News/read','GET|POST|PUT|DELETE|PATCH|*');
方式(2)
Route::快捷方法名('路由表达式', '路由地址');
//例如:
Route::get('new/' ,'News/read');
Route::post('new/' ,'News/update');
Route::put('new/:id','News/update');
Route::delete('new/:id','News/delete');
Route::any('new/:id','News/read'); // 所有请求都支持的路由规则
变量(参数)
变量 :year 等价于 <year>
可选变量 [:month]等价于 <month?>
比如:
Route::get('blog/:year/[:month]','Blog/archive');
// 等价于
Route::get('blog//' ,'Blog/archive');
额外参数
//如果append方法中的变量和路由规则存在冲突的话,append方法传入的优先。
Route::get('blog/:id','blog/read')
->append(['status' => 1, 'app_id' =>5]);
完全匹配
// config/route.php 全局开启
'route_complete_match' => true,
// 单路由开启(类似正则表达式的以$符结尾)
Route::get('new/:cate$', 'News/category');
// 单路由关闭
Route::get('new/:cate', 'News/category')->completeMatch(false);
(给某个路由绑定一个唯一的)标志
// 相当于给'News/read'绑定了一个别名'new_read',
// 可以这样使用url('new_read', ['id' => 10]);
Route::rule('new/:id','News/read')
->name('new_read');
例子
示例环境说明:我这里设置了虚拟域名tp.com,并且是多应用模式,当前应用是index
路由配置
use think\facade\Route;
Route::get('/r1','index/route1')->name('r1');
Route::get('/r2//' ,'index/route2');
Route::get('/r3///' ,'index/route3')->append(['appid'=>'tp6']);
控制器
namespace app\index\controller;
use think\Request;
use app\BaseController;
class Index extends BaseController
{
public function route1(Request $request)
{
echo 'route1
';
echo url('r1');
// 浏览器输入:
// http://tp.com/index/r1
// 浏览器输出:
// route1
// /index/r1.html(在路由配置中,设置了->name('r1')标志)
}
public function route2(Request $request, $id, $name='')
{
echo 'route2
';
echo '$id:'.$id.'
';
echo '$name:'.$name.'
';
// 浏览器输入:
// http://tp.com/index/r2/22
// 浏览器输出:
// route2
// $id:25(注意看路由配置,id是必传的变量,不传会报错)
// $name:(name变量是可选,所以route2方法定义时,$name要给一个默认值,不然会报错)
}
public function route3(Request $request, $id, $name='', $appid)
{
echo 'route2
';
echo '$id:'.$id.'
';
echo '$name:'.$name.'
';
echo '$appid:'.$appid.'
';
// 浏览器输入:
// http://tp.com/index/r3/22/zhangsan/thinkphp
// 浏览器输出:
// route3
// $id:25(注意看路由配置,id是必传的变量,不传会报错)
// $name:zhangsan(name变量是可选,所以route2方法定义时,$name要给一个默认值,不然会报错)
// $appid:tp6(这里为什么不是我们在url里传的thinkphp?因为我们在路由配置中设置了额外参数->append(['appid'=>'tp6']),当冲突时,优先取额外参数传值)
}
}