- 删除 tools:agent:publish 整套(不再兼容多套 IDE,只保留 .agents 目录) - helper.php 全部 27 个全局函数加 if (!function_exists()) 包裹,项目侧可在 app/common.php 定义同名函数覆盖 - ulthon-file-override-mechanism.md 新增全局函数覆盖章节 - AGENTS.md 删除智能体指导章节,PHP 8+ 改为 8.0+,MySQL 8+ 改为 5.7+ - AGENTS.md 项目结构树补全 tests/、extend/think/、source/ 子项 - README.md PHP 版本统一为 8.0+ - ulthon-base-app-architecture SKILL 路径补 admin/service/ 段 - ulthon-tools-http-call SKILL 补 --page-data 参数 - ulthon-naming-convention 补元数据头 - ulthon-update-workflow 统一 extend/think/ 归类
6.8 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 里的所有全局函数都有 if (!function_exists('xxx')) 包裹。项目侧如需覆盖某个全局函数的行为(例如修复框架 bug 或调整实现),只需在 app/common.php 的 include helper.php 语句之前定义同名函数即可。
加载顺序:app/common.php 先执行 → 项目侧函数先定义 → include helper.php 时 if (!function_exists()) 检查发现已存在 → 跳过框架版本。
示例:
// app/common.php
function sysconfig($group, $name = null, $default = null) {
// 项目侧自定义实现
return my_custom_logic($group, $name, $default);
}
include App::getRootPath() . '/extend/base/helper.php';
注意:该机制是"函数级覆盖",与本文档前述三类"文件级覆盖"是独立机制。helper.php 中已包裹的函数清单见源码(截至当前版本共 27 个:__url、flow_url、password、xdebug、sysconfig、array_format_key、auth、get_session_admin、read_header_token、json_message、unparse_url、build_upload_url、event_handle_result、event_handle_string、event_view_content、event_view_replace、event_view_replace_js、event_response、app_file_path、array_to_table、format_bytes、parse_bytes、get_store_value、set_store_value、get_site_version_key、format_null_value、ctype_numeric)。
相关文件
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加载定时器配置)