🛣️ 路由配置

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. 路由文件位置不正确
  2. 路由语法错误
  3. 缓存未清理

解决方法

# 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:路由冲突怎么办?

解决方法

  1. 调整路由顺序:更具体的路由放在前面
  2. 使用不同的路径:避免路径重复
  3. 使用路由分组:组织相关路由
<?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);
    }
}
最近更新:
Contributors: 邹景立, Anyon