mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2026-06-07 04:28:11 +08:00
补充 v8 重构后的架构文档、组件说明和迁移记录,方便后续维护者理解插件边界。 主要内容: - 更新根 README,说明 v8 插件分层、系统模块、交付命令和验证流程。 - 新增组件明细、插件边界、路由分发、软删除和稳定性文档。 - 记录 Storage 合并到 System、旧 View 移除和 Helper 并入 System 的决策。 - 补充文档注释报告和后续重构计划,便于持续演进。
119 lines
3.3 KiB
Markdown
119 lines
3.3 KiB
Markdown
# 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. 单条路由
|
||
|
||
```php
|
||
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);
|
||
```
|
||
|
||
约束:
|
||
|
||
- `portal`、`open-upload` 是根路由规则
|
||
- `home/index`、`api.upload/file` 是目标应用内部相对路径
|
||
- 不再推荐把目标地址写成带应用前缀的旧三段式
|
||
|
||
### 2. 分组路由
|
||
|
||
```php
|
||
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. 兼容旧路由
|
||
|
||
以下旧写法仍会尝试做目标推断:
|
||
|
||
```php
|
||
Route::rule('legacy-demo', 'index/demo/index');
|
||
Route::rule('legacy-login', 'system/login/index');
|
||
```
|
||
|
||
兼容规则只用于过渡:
|
||
|
||
- 如果第一段能识别为插件编码,优先按插件处理
|
||
- 否则如果第一段能识别为本地应用编码,按本地应用处理
|
||
|
||
新代码不要继续依赖这种隐式推断。
|
||
|
||
## 为什么这样最好
|
||
|
||
这套机制的关键价值是“先选上下文,再执行路由”。
|
||
|
||
只要目标应用/插件已经在分发前绑定完成,后面的控制器解析、模板加载、配置加载和中间件链都会落在正确目录,不需要再用各种运行时补丁去修视图路径或命名空间。
|
||
|
||
这比单纯在 `MultAccess` 里追加更多 if/else 更稳,因为:
|
||
|
||
- 路由语义在注册阶段就是显式的
|
||
- 全局路由不会再偷偷依赖当前默认应用
|
||
- 本地多应用和插件机制可以同时存在
|
||
- 迁移旧路由时有明确新标准和兼容兜底
|
||
|
||
## 推荐约束
|
||
|
||
- 根目录 `route/*.php` 只写跨应用或跨插件的全局路由
|
||
- 应用内部路由放各自 `app/{name}/route` 或 `plugin/*/src/route`
|
||
- 根路由一律使用 `bindApp` / `bindPlugin` / `appGroup` / `pluginGroup`
|
||
- 如果必须保留旧三段式,后续要逐步迁成显式目标声明
|