mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-08-30 12:45:32 +08:00
- 新增 ulthon-file-override-mechanism.md:阐述 app/ 覆盖 extend/base/ 的三类机制(视图模板、include 标签、app_file_path)与不支持覆盖的反例清单 - ulthon-base-app-architecture:升格原孤立描述为独立小节"5. 文件级覆盖机制" - ulthon-timer:在 app_file_path 覆盖说明处增加规则引用 - AGENTS.md:登记新规则到框架内置规则索引 - ulthon-rules-manager:修订索引职责(AGENTS.md 仅 ulthon-、PROJECT.md 仅 project-,互斥不重复维护);索引格式从 4 列改为 3 列与项目实际一致;维护规则补充对称约束;泛化"迁移现有内容"章节
5.4 KiB
5.4 KiB
文件级覆盖机制(app/ 覆盖 extend/base/)
来源:框架内置(ulthon-) 作用域:所有"框架默认文件 → 业务同名文件"的覆盖场景(视图模板、include 标签、
app_file_path()加载的 PHP/配置/模板) 触发条件:需要替换框架内置视图/模板/跳转页/异常页/定时任务配置/CURD 模板/版本升级钩子时加载
规则内容
概述
Ulthon Admin 在"类继承覆盖"之外,还提供"文件级覆盖"能力:业务侧在 app/ 下放置与 extend/base/ 同路径、同名的文件,框架运行时会优先加载 app 版本。
该机制只对特定类型的文件生效,不是所有文件都支持。覆盖能力分三类:
- 机制一:视图模板覆盖(最核心、最隐蔽,控制器
fetch()自动生效) - 机制二:模板内
{include}标签覆盖(与机制一同源) - 机制三:
app_file_path()辅助函数显式覆盖(需调用方主动使用)
机制一:视图模板覆盖
- 实现位置:
extend/think/view/driver/Think.php:160-257的parseTemplate()方法 - 不走
app_file_path,由视图驱动自身完成三级回退查找:app/<module>/view/<template>.html(最高优先,app 应用视图)extend/base/<module>/view/<template>.html(框架兜底视图)<root>/view/<template>.html(根目录全局视图,最低优先)
- 触发场景:所有控制器
fetch()渲染视图时(经ViewBase::fetch()→think.View::fetch()→Think::fetch()→parseTemplate()) - 业务侧用法:在
app/<module>/view/下放同名.html即可覆盖框架视图
机制二:模板内 {include} 标签覆盖
- 实现位置:
extend/think/Template.php:1192-1248的parseTemplateFile()方法 - 查找逻辑:与机制一相同的三级查找(
app_path/base_app_path/view_app_path,由Think.php:196-198注入到 Template 实例) - 前缀规则:
@/开头:从根目录定位(三级路径都设为同一个view_root_path)@开头:从控制器视图目录定位(用base_view_path)./开头:相对当前模板文件目录- 无前缀:走完整三级查找
- 触发场景:模板编译时解析
{include file="..."}标签
机制三:app_file_path() 辅助函数
- 定义位置:
extend/base/helper.php:392-400 - 加载入口:
app/common.php:6(唯一 include 点;这是 AGENTS.md 中明确的全局辅助函数唯一特许) - 查找层级(两级回退):
app/<相对路径>(最高优先)extend/base/<相对路径>(兜底)
- 函数签名约束(来自源码注释):
- 第一个参数
$file_path不要以/开头 - 不需要以
app开头 - 函数内部会自动定位
app/或extend/base/
- 第一个参数
已知调用点(业务侧可在 app/ 同路径下覆盖其中任一)
| 调用点 | 相对路径参数 | 文件类型 | 业务意义 |
|---|---|---|---|
config/app.php:35 |
common/tpl/think_exception(_debug).tpl |
异常模板 | 调试异常页 |
config/app.php:37,39 |
common/tpl/dispatch_jump.tpl |
跳转模板 | success/error 跳转页 |
TimerServiceBase:19,71 |
common/command/timer/config.php |
配置数组 | 定时任务列表(可被业务定制) |
AdminUpdateCodeServiceBase:23 |
admin/service/adminUpdateCodeData/{version}.php |
PHP 钩子文件 | 版本升级时执行的迁移代码 |
MigrateBase:207 |
common/command/curd/migrate.tpl |
视图模板 | CURD 生成迁移代码的模板 |
反例:以下场景不支持文件级覆盖
下列路径与机制都不走 app/base 覆盖,业务侧在 app/ 下放同名文件不会生效:
AdminInitServiceBase::requireData()(extend/base/admin/service/AdminInitServiceBase.php:139):用__DIR__直接定位extend/base/admin/service/adminInitData/,不支持 app 覆盖- 命令注册(
config/console.php):空commands数组,命令通过 SPI 自动扫描app/common/command/,不走覆盖 - 语言包(
config/lang.php):标准 ThinkPHP 机制,不支持 app/base 覆盖 - 路由(
route/app.php):空文件,无覆盖机制 - 静态资源(
public/static/):Filesystem disk 加载,无覆盖机制 - 配置目录(
config/*):标准 ThinkPHP 配置加载,无 app/base 覆盖机制
与"类继承覆盖"的关系
类继承层面的 Base/App 覆盖(如 app\<Class> extends base\<Class>Base)属于另一套机制,详见技能:ulthon-base-app-architecture。本规则只讲"文件级"覆盖,不涉及类的继承重写。
业务侧使用范例
- 覆盖异常页样式:在
app/common/tpl/think_exception.tpl放同名文件 - 覆盖定时任务配置:在
app/common/command/timer/config.php放同名文件(实际项目已在用) - 覆盖某控制器视图:在
app/admin/view/<controller>/<action>.html放同名文件 - 覆盖 CURD 迁移模板:在
app/common/command/curd/migrate.tpl放同名文件
相关文件
extend/base/helper.php(app_file_path()定义)app/common.php(辅助函数唯一加载入口)extend/think/view/driver/Think.php(视图驱动parseTemplate())extend/think/Template.php(模板编译parseTemplateFile())
相关技能
- ulthon-base-app-architecture
- ulthon-timer(使用
app_file_path加载定时器配置)