🛣️ 路由配置
ThinkAdmin 基于 ThinkPHP8(兼容 ThinkPHP6)的多应用平台,提供了灵活的路由管理机制。路由被划分为全局路由和应用路由两大类,满足不同场景的需求。
📚 基础概念
🤔 基本介绍
路由是 URL 地址到控制器方法的映射关系。
简单理解:就像快递地址,路由告诉系统"这个 URL 应该访问哪个控制器的方法"。
实际例子:
用户访问:http://example.com/admin/user/index
↓
路由系统解析:这是 admin 应用的 user 控制器的 index 方法
↓
执行代码:app\admin\controller\User::index()
↓
返回结果:HTML 页面或 JSON 数据不使用路由的情况:
用户访问:http://example.com/index.php/admin/user/index
↓
直接执行:app\admin\controller\User::index()使用路由后:
用户访问:http://example.com/user/list
↓
路由映射:/user/list → admin/user/index
↓
执行代码:app\admin\controller\User::index()🤔 使用优势
问题1:URL 不友好
不使用路由时,URL 可能很长很复杂:
❌ 不友好:http://example.com/index.php/admin/user/index?id=123&type=list
✅ 友好:http://example.com/user/123/list问题2:暴露文件结构
不使用路由时,URL 会暴露真实的文件路径:
❌ 暴露结构:http://example.com/index.php/admin/user/index
✅ 隐藏结构:http://example.com/user/list问题3:不够灵活
使用路由后,可以自定义 URL 规则:
// 可以将 /user/list 映射到 /admin/user/index
app()->route->get('user/list', 'admin/user/index');⚙️ 工作原理
路由系统的工作流程是自动的,开发者只需配置路由规则:
步骤1:用户访问 URL
用户在浏览器输入:http://example.com/admin/user/index步骤2:路由系统解析
ThinkAdmin 的路由系统会自动解析 URL:
// 系统自动解析 URL
// /admin/user/index
// ↓
// 应用:admin
// 控制器:User
// 方法:index步骤3:查找路由规则
系统会先查找是否有自定义路由规则:
// 如果配置了路由
app()->route->get('user/list', 'admin/user/index');
// 访问 /user/list 会映射到 /admin/user/index
// 如果没有配置路由
// 直接使用默认规则:/admin/user/index步骤4:执行控制器方法
找到对应的控制器和方法后,执行代码:
// 执行控制器方法
$controller = new \app\admin\controller\User();
$result = $controller->index();步骤5:返回响应
将执行结果返回给用户:
// 返回 HTML 页面或 JSON 数据
return $result;📖 相关概念
URL(统一资源定位符)
- 网页的地址,如
http://example.com/admin/user/index - 由协议、域名、路径组成
- 路由系统主要处理路径部分
控制器(Controller)
- 处理请求的类
- 位于
app/{应用}/controller/目录 - 继承
think\admin\Controller类
方法(Method)
- 控制器中的函数
- 处理具体的业务逻辑
- 如
index()、save()、delete()等
路由规则
- URL 路径到控制器方法的映射
- 可以自定义 URL 格式
- 支持参数传递
🚀 路由类型
ThinkAdmin 支持两种路由类型,适用于不同的场景:
🌐 全局路由
全局路由适用于整个系统,可以监听根路径(不包含应用前缀)。
特点:
- 适用于所有应用
- 监听根路径,如
/demo、/api/test - 在应用
sys.php文件或插件服务类中注册 - 优先级高于应用路由
使用场景:
- 跨应用的公共接口
- 第三方回调接口
- 特殊的 URL 规则
示例:
// 访问:http://example.com/demo
// 不需要应用前缀,直接访问根路径
app()->route->get('demo', 'admin/test/index');📱 应用路由
应用路由只适用于特定应用,位于各应用的 route 目录下。
特点:
- 只适用于当前应用
- 需要应用前缀,如
/admin/user/list - 位于
app/{应用}/route/目录 - 按模块进行划分和管理
使用场景:
- 应用内部的 URL 美化
- 应用特定的路由规则
- 模块化的路由管理
示例:
// 访问:http://example.com/admin/user/list
// 需要 admin 应用前缀
app()->route->get('user/list', 'user/index');📋 路由特点
- 模块化管理: 每个模块拥有独立的路由配置
- 灵活配置: 支持多种路由定义方式
- 自动加载: 系统自动加载并应用路由配置
- 互不干扰: 不同模块间的路由互不冲突
- 动态注册: 支持运行时动态注册路由
- 缓存优化: 支持路由缓存提升性能
- 中间件支持: 支持路由中间件处理
- 参数绑定: 支持路由参数自动绑定
🌐 全局路由
在ThinkAdmin中,全局路由具备监听根路径的能力,如 /my-test.html 等路径,都可通过全局路由进行处理。然而,全局路由的注册并非通过传统的配置文件或路由定义文件实现,而是需要在每个应用的 sys.php 文件或插件服务类中动态完成。
例如,在 admin 应用模块中,开发者可以在 admin/sys.php 文件中编写代码来注册全局路由。同样地,在应用插件的服务类中也可以进行全局路由的注册操作。这种动态注册的方式赋予了开发者更大的灵活性,可以根据应用需求实时调整路由规则,而无需修改框架的核心配置。
通过这一优化,ThinkAdmin 的路由管理更加高效和便捷,能够满足复杂应用场景的需求,提升开发效率和系统性能。同时,也要求开发者对 ThinkPHP8(兼容 ThinkPHP6)的路由机制有深入的了解,以便正确地进行路由注册和管理。
<?php
// app/admin/sys.php 或插件 Service.php 中
// 访问入口 index.php
// 访问地址 https://yourdomain.com/demo
// 路由配置 app/admin/sys.php(当然放其他应用目录也是一样的)
app()->route->get('demo', 'myself/test'); // 访问 /demo 映射到 /myself/test
// 也可以使用其他路由方法
app()->route->post('api/user', 'user/api'); // POST 请求
app()->route->any('test', 'test/index'); // 支持所有请求方法
app()->route->group('v1', function() {
app()->route->get('user', 'user/index');
app()->route->post('user', 'user/save');
}); // 路由分组📱 应用路由
在 ThinkAdmin 中,路由的配置和管理是按模块进行划分的,每个模块拥有独立的路由配置,确保了模块间的路由互不干扰,提高了系统的可维护性和扩展性。 具体而言,每个模块的路由配置文件通常位于该模块的 route 目录下,例如 admin/route/demo.php。当系统启动时,会自动加载并应用这些路由配置文件。这意味着在应用模块或应用插件的 route 目录下的所有PHP文件都会被解析并生效,从而实现对应模块的路由功能。
这种按模块配置路由的方式,使得开发者可以更加清晰地组织和管理路由规则,避免了路由规则的混乱和冲突。同时,也使得不同模块之间的路由可以独立进化,互不干扰,提高了系统的灵活性和可定制性。 通过这一优化,ThinkAdmin 的路由管理更加规范化和模块化,为开发者提供了更加清晰和便捷的路由配置方式,提升了开发效率和系统性能。
<?php
// app/admin/route/demo.php
// 访问入口 index.php
// 访问地址 https://yourdomain.com/admin/demo
// 路由配置 app/admin/route/demo.php
app()->route->get('demo', 'test'); // 访问 /admin/demo 映射到 /admin/test
// 访问入口 index.php
// 访问地址 https://yourdomain.com/admin/demo2
// 路由配置 app/admin/route/demo.php
app()->route->any('demo2', 'user/index'); // 访问 /admin/demo2 映射到 /admin/user/index
// 也可以返回数组方式定义路由
return [
'demo' => 'test',
'demo2' => 'user/index',
];应用绑定路由
做应用绑定,可以去除模块名称,如入口为 admin.php,自动绑定应用为 admin:
<?php
// app/admin/route/demo.php
// 访问入口 admin.php(绑定 admin 应用)
// 访问地址 https://yourdomain.com/demo(不需要 /admin 前缀)
// 路由配置 app/admin/route/demo.php
app()->route->get('demo', 'test'); // 访问 /demo 映射到 /admin/test默认应用路由
由于多应用模式,默认绑定应用 index:
<?php
// app/index/route/demo.php
// 访问入口 index.php
// 访问地址 https://yourdomain.com/demo
// 路由配置 app/index/route/demo.php
app()->route->get('demo', 'test'); // 访问 /demo 映射到 /index/test❓ 常见问题
Q1:路由不生效?
可能原因:
- 路由文件位置不正确
- 路由语法错误
- 缓存未清理
解决方法:
# 1. 检查路由文件位置
# 全局路由:app/{应用}/sys.php
# 应用路由:app/{应用}/route/*.php
# 2. 清理路由缓存
php think clear
# 或
rm -rf runtime/cache/*
# 3. 检查路由语法
# 确保路由文件返回正确的格式Q2:如何调试路由?
方法1:查看路由列表
# 查看所有注册的路由
php think route:list方法2:开启路由调试
// config/route.php
return [
'url_route_on' => true,
'url_route_must' => false,
'route_complete_match' => false,
'url_domain_deploy' => false,
];Q3:路由参数如何获取?
在控制器中获取:
<?php
// 路由:user/:id
// 访问:/admin/user/123
class User extends Controller
{
public function detail()
{
// 方式1:使用 request 对象
$id = $this->request->param('id');
// 方式2:使用 input() 函数
$id = input('id');
// 方式3:使用助手函数
$id = request()->param('id');
}
}Q4:如何实现 RESTful 路由?
使用路由分组:
<?php
// app/admin/route/api.php
return [
// RESTful 风格路由
'api/user' => [
['user/index', 'get'], // GET /admin/api/user
['user/save', 'post'], // POST /admin/api/user
['user/:id', 'get'], // GET /admin/api/user/123
['user/:id', 'put'], // PUT /admin/api/user/123
['user/:id', 'delete'], // DELETE /admin/api/user/123
],
];Q5:路由冲突怎么办?
解决方法:
- 调整路由顺序:更具体的路由放在前面
- 使用不同的路径:避免路径重复
- 使用路由分组:组织相关路由
<?php
// ❌ 错误:路由冲突
return [
'user' => 'user/index',
'user' => 'user/list', // 冲突
];
// ✅ 正确:使用不同路径
return [
'user' => 'user/index',
'user/list' => 'user/list', // 不冲突
];
// ✅ 正确:使用路由分组
return [
'user' => [
'' => 'user/index',
'list' => 'user/list',
],
];Q6:如何实现路由中间件?
在路由中应用中间件:
<?php
// app/admin/route/api.php
// 方式1:在路由定义中应用
app()->route->get('user', 'user/index')->middleware('auth');
// 方式2:在路由分组中应用
app()->route->group('api', function() {
app()->route->get('user', 'user/index');
})->middleware('auth');中间件类:
<?php
// app/admin/middleware/Auth.php
namespace app\admin\middleware;
class Auth
{
public function handle($request, \Closure $next)
{
// 验证用户是否登录
if (!AdminService::isLogin()) {
return redirect('/admin/login');
}
return $next($request);
}
}