ThinkAdmin/docs/architecture/route-dispatch-standard.md
Anyon 6f4056f64d docs(architecture): 完善 v8 架构与迁移说明
补充 v8 重构后的架构文档、组件说明和迁移记录,方便后续维护者理解插件边界。

主要内容:

- 更新根 README,说明 v8 插件分层、系统模块、交付命令和验证流程。

- 新增组件明细、插件边界、路由分发、软删除和稳定性文档。

- 记录 Storage 合并到 System、旧 View 移除和 Helper 并入 System 的决策。

- 补充文档注释报告和后续重构计划,便于持续演进。
2026-05-08 15:31:22 +08:00

3.3 KiB
Raw Blame History

Route Dispatch Standard

目标

当前项目的最佳实践不是让根路由“先命中、后猜应用”,而是让根路由先声明目标应用或插件,再进入真实调度。

这样可以在分发前就绑定正确的:

  • 应用目录
  • 命名空间
  • view_path
  • 应用级配置
  • 中间件
  • 语言包
  • 插件入口类型(web / api

否则全局路由虽然能命中,但很容易出现这些问题:

  • 模板从错误目录加载
  • 控制器命名空间错误
  • 插件 API 被当成普通页面入口
  • 本地应用配置和中间件没有生效

当前标准

1. 本地与插件模型

  • app/*:本地多应用
  • plugin/*:插件应用
  • 默认本地应用:index

2. 分发优先级

MultAccess 当前的标准优先级是:

  1. 显式插件前缀
  2. 显式本地应用前缀
  3. 根路由声明的目标应用/插件
  4. 动态插件切换(兼容入口,默认关闭)
  5. 默认本地应用

3. 标准入口

  • 本地应用显式入口:/{app}/{controller}/{action}
  • 默认本地应用:生成 URL 时可省略 index
  • 插件页面入口:/{plugin}/{controller}/{action}
  • 插件 API 入口:/api/{plugin}/{controller}/{action}

路由注册标准

1. 单条路由

use think\admin\runtime\RequestContext;
use think\facade\Route;

Route::bindApp('portal', 'home/index', 'index');
Route::bindPlugin('open-upload', 'api.upload/file', 'system', RequestContext::ENTRY_API);

约束:

  • portalopen-upload 是根路由规则
  • home/indexapi.upload/file 是目标应用内部相对路径
  • 不再推荐把目标地址写成带应用前缀的旧三段式

2. 分组路由

use think\admin\runtime\RequestContext;
use think\facade\Route;

Route::appGroup('member', function () {
    Route::get('member-center', 'center/index');
});

Route::pluginGroup('system', function () {
    Route::get('quick-upload', 'api.upload/file');
}, RequestContext::ENTRY_API);

这适合一批根路由都指向同一个本地应用或插件的场景。

3. 兼容旧路由

以下旧写法仍会尝试做目标推断:

Route::rule('legacy-demo', 'index/demo/index');
Route::rule('legacy-login', 'system/login/index');

兼容规则只用于过渡:

  • 如果第一段能识别为插件编码,优先按插件处理
  • 否则如果第一段能识别为本地应用编码,按本地应用处理

新代码不要继续依赖这种隐式推断。

为什么这样最好

这套机制的关键价值是“先选上下文,再执行路由”。

只要目标应用/插件已经在分发前绑定完成,后面的控制器解析、模板加载、配置加载和中间件链都会落在正确目录,不需要再用各种运行时补丁去修视图路径或命名空间。

这比单纯在 MultAccess 里追加更多 if/else 更稳,因为:

  • 路由语义在注册阶段就是显式的
  • 全局路由不会再偷偷依赖当前默认应用
  • 本地多应用和插件机制可以同时存在
  • 迁移旧路由时有明确新标准和兼容兜底

推荐约束

  • 根目录 route/*.php 只写跨应用或跨插件的全局路由
  • 应用内部路由放各自 app/{name}/routeplugin/*/src/route
  • 根路由一律使用 bindApp / bindPlugin / appGroup / pluginGroup
  • 如果必须保留旧三段式,后续要逐步迁成显式目标声明