简介
本技术文档聚焦 DouPHP 的“工具服务”能力,围绕搜索引擎优化(SEO)、站点地图生成、视图渲染辅助、数据处理等基础功能展开。重点说明后台工具服务类(目录权限检测、URL 批量替换、后台目录更名、布尔字段切换、编辑器切换、排序工具)以及前台 SEO 元信息解析、站点地图生成、视图数据组装等关键实现;同时给出与业务控制器协作方式、开发示例、性能优化策略与配置扩展点。
项目结构
DouPHP 将“工具服务”按职责分层组织:
- 后台工具服务:位于 admin/service/tool,提供系统级运维与内容维护工具。
- 前台 SEO 与站点地图:位于 front/service/seo 与 front/service/sitemap,负责页面 SEO 元信息与站点地图生成。
- 控制器层:admin/controller/tool 暴露后台工具入口;front/controller/sitemap 暴露站点地图入口;各业务控制器(如视频、积分、单页)通过注入 SeoResolver 完成 SEO 元信息设置。
- 系统服务:core/service/system 提供模块特性开关、语言清单、常量读取等系统级支撑。
graph TB
subgraph "后台"
TC["ToolController"] --> TS["ToolService"]
end
subgraph "前台"
SC["SitemapController"] --> SS["SitemapService"]
VC["VideoController"] --> SR["SeoResolver"]
PC["PointController"] --> SR
PG["PageController"] --> SR
end
subgraph "系统"
CMS["CoreModuleSettings"]
MFG["ModuleFeatureGate"]
MLM["ModuleLanguageManifest"]
MSR["ModuleSettingReader"]
SCR["SystemConstantsReader"]
end
TS -.-> CMS
TS -.-> MFG
TS -.-> MSR
SS -.-> SCR
SR -.-> MSR
核心组件
- 后台工具服务(ToolService)
- 目录权限检测:递归检查 storage、images、theme 等关键目录读写状态,输出可展示的行数据。
- URL 批量替换:基于配置中的模块列/单页表,对正文域进行域名替换。
- 后台目录更名:两阶段安全改名(校验→一次性引导脚本),兼容 Windows 句柄占用问题。
- 列表布尔字段切换:Ajax 翻转 0/1 并返回新值与文案。
- 编辑器切换:在 editor 与 vditor 间切换配置。
- 排序工具:重置 sort 或开启/关闭拖拽排序会话开关。
- 前台 SEO 解析器(SeoResolver)
- 统一标题拼接规则:首页、分类、详情、单页、归档等场景。
- keywords/description 回退到站点配置,支持归档追加标签。
- 站点地图(SitemapController + SitemapService)
- 对外提供 sitemap.xml 生成接口,内部聚合多模块链接。
- 系统服务(core/service/system)
- 模块特性开关、语言清单、常量读取、模块设置读取,为工具与业务提供系统级能力。
架构总览
下图展示了工具服务与控制器、服务之间的调用关系与数据流向。
sequenceDiagram
participant Admin as "管理员浏览器"
participant TCtrl as "ToolController"
participant TSvc as "ToolService"
participant DB as "数据库"
participant FS as "文件系统"
Admin->>TCtrl : 访问目录检测/URL替换/目录更名
TCtrl->>TSvc : 调用 buildDirectoryCheckData/storeReplaceUrl/prepareAdminDirRename
alt 目录检测
TSvc->>FS : 检查storage/images/theme等目录权限
TSvc-->>TCtrl : 返回writeable_list
else URL替换
TSvc->>DB : 遍历配置模块列/单页表替换域名
TSvc-->>TCtrl : 成功
else 目录更名
TSvc->>FS : 写入一次性引导脚本(storage/cache)
TCtrl-->>Admin : 302跳转至引导脚本
Admin->>FS : 执行一次性脚本(rename+写state+自删)
end
详细组件分析
后台工具服务(ToolService)
- 目录权限检测
- 收集 storage 根及其子目录、images、theme 等关键路径,逐项检测读写状态,输出带提示文案的行数据供界面展示。
- URL 批量替换
- 从配置中获取模块列与单页表集合,使用参数化绑定对正文域执行批量替换,避免 SQL 注入与双重转义。
- 后台目录更名
- 名称合法性校验(仅字母数字点下划线横杠,排除保留名),禁止大写,目标不可冲突。
- 生成一次性引导脚本(含 token 校验、有效期、重试 rename、模板编译目录同步、写 state/admin_dir.php、自删除)。
- 控制器收到返回的重定向 URL 后 302 跳转,由独立请求完成改名。
- 布尔字段切换
- 读取当前值取反后更新,返回新值与本地化文案。
- 编辑器切换
- 在 editor 与 vditor 之间切换 site.editor 配置。
- 排序工具
- reset 将指定模块全部 sort 置默认值;open/close 控制会话内排序模式开关。
flowchart TD
Start(["进入 prepareAdminDirRename"]) --> Validate["校验旧/新目录名<br/>保留名与大写检查"]
Validate --> |非法| ThrowErr["抛出异常并返回上一页"]
Validate --> |合法| CheckExist{"旧目录存在且新目录不存在?"}
CheckExist --> |否| ThrowErr
CheckExist --> |是| GenScript["生成一次性引导脚本(storage/cache)"]
GenScript --> ReturnURL["返回重定向URL(含token)"]
ReturnURL --> End(["控制器302跳转"])
前台 SEO 解析器(SeoResolver)
- 标题构建
- 首页:site_title + 后缀(授权时不输出)。
- 分类/详情:title + 分类名 + 模块名 + site_name + 后缀。
- 单页:title + site_name + 后缀。
- 归档:站点首页标题 + 年月标签。
- 关键词与描述
- 优先使用传入值,为空则回退到站点配置;归档场景追加时间标签。
- 国际化与语言值
- 根据 locale 与语言包获取分类名等动态文本。
classDiagram
class SeoResolver {
+pageTitle(module, class, title, archive) string
+keywords(value, archive) string
+description(value, archive, module) string
-build(module, class, title) string
}
站点地图(SitemapController + SitemapService)
- 控制器负责路由与响应,服务负责聚合各模块链接并生成 XML。
- 典型流程:请求 /sitemap.xml → 控制器调用服务 → 服务查询各模块活跃条目 → 组装 XML → 返回响应。
sequenceDiagram
participant Client as "客户端"
participant SCtrl as "SitemapController"
participant Svc as "SitemapService"
participant DB as "数据库"
Client->>SCtrl : GET /sitemap.xml
SCtrl->>Svc : generate()
Svc->>DB : 查询各模块有效条目
DB-->>Svc : 结果集
Svc-->>SCtrl : XML字符串
SCtrl-->>Client : 200 text/xml
视图渲染与业务控制器协作
- 业务控制器(如 VideoController、PointController、PageController)通过注入 SeoResolver 设置页面标题,结合导航与面包屑构建页面骨架,再交由模板引擎渲染。
- 分页、归档、分类等逻辑由对应 Service 处理,控制器负责组装视图数据。
sequenceDiagram
participant C as "控制器"
participant S as "业务Service"
participant SEO as "SeoResolver"
participant V as "视图模板"
C->>S : 构建列表/详情数据
S-->>C : 数据对象
C->>SEO : pageTitle()/keywords()/description()
SEO-->>C : 元信息
C->>V : 渲染(dwt)
V-->>C : HTML
依赖关系分析
- ToolService 依赖:
- 数据库:用于 URL 替换、布尔字段切换、排序重置。
- 文件系统:存储运行时状态、图片与模板目录、一次性引导脚本。
- 配置:模块列/单页表、站点配置项。
- SeoResolver 依赖:
- 配置:站点标题、关键词、描述、授权状态。
- 数据库:分类表查询以获取分类名。
- 国际化:语言包与本地化。
- SitemapService 依赖:
- 数据库:聚合各模块有效条目。
- 配置:站点基础信息与分页/限制策略。
- 系统服务:
- CoreModuleSettings/ModuleFeatureGate:模块特性开关。
- ModuleLanguageManifest:语言清单。
- ModuleSettingReader/SystemConstantsReader:模块设置与常量读取。
graph LR
TS["ToolService"] --> DB["数据库"]
TS --> FS["文件系统"]
TS --> CFG["配置中心"]
SR["SeoResolver"] --> DB
SR --> CFG
SR --> I18N["国际化"]
SS["SitemapService"] --> DB
SS --> CFG
SYS["系统服务(core/service/system)"] --> TS
SYS --> SR
SYS --> SS
性能考虑
- 搜索索引构建
- 若引入全文检索,建议增量索引与定时重建,避免全量扫描;对高频查询字段建立合适索引。
- 缓存机制
- 站点地图与 SEO 元信息可结合缓存策略(如内存缓存或文件缓存),减少重复计算与数据库压力。
- 后台工具的一次性脚本与状态文件应设置合理过期清理策略(已内置 1 小时清理)。
- 资源压缩
- 前端静态资源启用 Gzip/Brotli 压缩与浏览器缓存(ETag/Cache-Control),降低带宽与请求开销。
- 数据库优化
- URL 批量替换采用参数化绑定,避免 SQL 注入与额外转义成本;分页查询添加必要索引。
- 并发与锁
- 目录更名脚本包含重试与短暂休眠,应对杀软/索引服务瞬时锁;确保跨平台一致性。
故障排查指南
- 目录权限不足
- 现象:无法上传或在线下载模板失败。
- 排查:使用后台“目录检测”查看 storage、images、theme 等目录状态,确保具备读写权限。
- URL 替换未生效
- 现象:正文域仍显示旧域名。
- 排查:确认配置中的模块列/单页表是否正确;检查替换范围是否覆盖目标字段;查看日志与数据库变更。
- 后台目录更名失败
- 现象:重定向后仍停留在原目录或报错。
- 排查:检查一次性脚本是否存在且未被拦截;确认目标目录未被占用;查看 storage/state 下的 admin_dir.php 是否更新。
- SEO 元信息不正确
- 现象:标题/关键词/描述不符合预期。
- 排查:检查控制器是否调用 SeoResolver 的相应方法;确认分类名与语言包是否正确;归档场景是否传递正确参数。
- 站点地图缺失链接
- 现象:sitemap.xml 未包含某些模块链接。
- 排查:确认模块是否启用、条目是否有效;检查 SitemapService 的数据源与过滤条件。
结论
DouPHP 的工具服务以后台工具与前台 SEO/站点地图为核心,提供了目录检测、URL 替换、目录更名、布尔字段切换、编辑器切换、排序工具等实用能力;同时通过 SeoResolver 统一 SEO 元信息生成,并通过 SitemapService 聚合站点地图。配合系统服务提供的模块特性、语言清单与常量读取,形成稳定可扩展的基础设施。建议在大规模数据与高并发场景下,结合缓存、索引与资源压缩策略进一步优化性能。
附录:配置与扩展接口
- 配置项
- 站点配置:site.site_title、site.site_keywords、site.site_description、site.editor、app.licensed 等,影响 SEO 元信息与编辑器行为。
- 模块配置:module.column_module、module.single_module,决定 URL 批量替换的目标表与字段。
- 分页配置:pagination.*,控制各模块列表分页大小。
- 扩展点
- 新增模块 SEO:在控制器中注入 SeoResolver,调用 pageTitle/keywords/description 设置元信息。
- 新增站点地图条目:在 SitemapService 中注册模块链接聚合逻辑。
- 新增后台工具:在 ToolController 中增加路由与方法,在 ToolService 中实现具体逻辑,必要时复用系统服务(模块特性、语言清单、常量读取)。
- 系统服务扩展:通过 CoreModuleSettings/ModuleFeatureGate/ModuleLanguageManifest/ModuleSettingReader/SystemConstantsReader 扩展模块能力与配置读取。