文档目录
案例表结构

简介

本设计文档聚焦 DouPHP 案例管理模块的数据库表结构设计,围绕案例主表与案例分类表展开,系统说明字段设计、状态与排序机制、层级与唯一标识策略,以及面向展示系统的查询优化建议。文档同时给出基于现有模型的 CRUD 使用指引与最佳实践,帮助开发者快速理解并正确使用案例数据。

项目结构

案例模块采用“前后端模型分离 + 统一 ORM”的组织方式:

  • 后台模型负责管理端的数据读写、过滤与默认排序等能力。
  • 前台模型负责展示层的数据读取、语言适配、附件 URL 预热、列表字段派生等。
  • 升级脚本负责历史表结构演进、字段补齐、命名规范化与时间字段统一。
  • 备份 SQL 提供最终表结构的参考定义。
graph TB
subgraph "后台"
A["admin/model/cases/Cases.php"]
B["admin/model/cases/CasesCategory.php"]
end
subgraph "前台"
C["front/model/cases/Cases.php"]
D["front/model/cases/CasesCategory.php"]
end
subgraph "数据层"
E["cases 表(dou_cases)"]
F["cases_category 表(dou_cases_category)"]
end
G["_update/data/upgrade.php"] --> E
G --> F
A --> E
B --> F
C --> E
D --> F

核心组件

  • 案例主表(dou_cases):承载案例标题、内容、图片、SEO 字段、点击统计、状态、排序、创建者信息、时间戳等。
  • 案例分类表(dou_cases_category):承载分类名称、唯一标识 slug、父级 parent_id、图标、SEO、是否同步导航、排序等。
  • 模型层:
    • 后台 Cases/CasesCategory:管理端写入、过滤、默认排序。
    • 前台 Cases/CasesCategory:展示端读取、语言适配、URL 与附件预热、列表字段派生。
  • 升级脚本:完成旧表到现表的迁移、字段补齐、命名规范、时间字段统一、索引完善。

架构总览

案例模块通过 ORM 将业务逻辑与数据表解耦,前台与后台共享同一套表结构,但关注点不同:

  • 后台侧重“写”:新增、编辑、删除、批量操作、默认排序策略。
  • 前台侧重“读”:发布态筛选、语言值覆写、附件 URL 预热、列表字段派生、归档筛选。
sequenceDiagram
participant Admin as "后台控制器"
participant AdminModel as "后台 Cases 模型"
participant DB as "数据库(cases)"
participant FrontModel as "前台 Cases 模型"
participant View as "模板/接口"
Admin->>AdminModel : 创建/更新案例(标题/内容/图片/SEO/状态/排序)
AdminModel->>DB : INSERT/UPDATE cases
Note over Admin,DB : 后台写入包含 operator_type/operator_id、created_at 等
View->>FrontModel : 获取已发布案例列表/详情
FrontModel->>DB : SELECT cases WHERE status=1 ...
FrontModel-->>View : 返回附带 category、image URL、多语言字段

详细组件分析

案例主表 dou_cases 设计

  • 主键:id(自增)。
  • 关联:category_id 指向 cases_category.id。
  • 内容字段:
    • title:案例标题(支持多语言覆写)。
    • content:案例正文(支持多语言覆写)。
    • image:主图(以附件编号存储,列表时自动解析为 URL)。
    • file:扩展附件(用于下载或更多资源)。
  • SEO 字段:
    • keywords:关键词。
    • description:描述。
  • 状态与排序:
    • status:发布状态(1 表示已发布)。
    • sort:手动排序权重(越小越靠前)。
  • 统计字段:
    • click:点击次数(用于热度统计)。
  • 创建者信息:
    • operator_type:创建者类型(admin/work)。
    • operator_id:创建者 ID。
  • 时间字段:
    • created_at:创建时间(由系统自动生成,勿手改)。
  • 其他:
    • defined:自定义字段对(用于扩展属性)。
    • slug:URL 友好标识(用于路由与 SEO)。
erDiagram
CASES {
int id PK
smallint category_id FK
enum operator_type
int operator_id
string title
string slug
text content
string image
string file
string keywords
string description
tinyint status
int sort
int click
datetime created_at
}

案例分类表 dou_cases_category 设计

  • 主键:id(自增,原 cat_id 已重命名为 id)。
  • 层级关系:parent_id 表示父分类,形成树形结构。
  • 唯一标识:slug(原 unique_id 已重命名为 slug),用于路由与 SEO。
  • 名称与 SEO:
    • name:分类名称(支持多语言覆写)。
    • keywords:关键词。
    • description:描述。
  • 展示控制:
    • icon:分类图标路径。
    • sync_to_nav:是否同步到导航。
    • sort:排序权重。
erDiagram
CASES_CATEGORY {
smallint id PK
string name
string slug
smallint parent_id
string icon
string keywords
string description
tinyint sync_to_nav
int sort
}

字段设计要点与用途

  • 标题与内容:title/content 支持多语言覆写,便于国际化站点展示。
  • 图片与附件:image 存储附件编号,列表时自动解析为 URL;file 用于额外附件。
  • SEO 字段:keywords/description 用于搜索引擎优化。
  • 点击统计:click 记录访问热度,可用于热门案例排序。
  • 状态管理:status=1 表示已发布,前台默认仅展示已发布项。
  • 排序机制:sort 配合 id 实现稳定排序;后台根据配置决定默认排序策略。
  • 创建者信息:operator_type/operator_id 支持多角色创建来源追踪。
  • 时间字段:created_at 统一时间格式,便于归档与时间范围筛选。

分类层级与唯一标识机制

  • 层级:通过 parent_id 构建分类树,支持多级分类组织。
  • 唯一标识:slug 作为分类的唯一标识,用于路由与 SEO;升级过程中已将 unique_id 重命名为 slug。
  • 同步导航:sync_to_nav 控制是否将分类纳入导航菜单。

状态管理与排序机制

  • 状态:status=1 表示已发布,前台默认仅返回已发布案例。
  • 排序:
    • 前台默认:按 sort ASC、id DESC 排序。
    • 后台默认:根据配置 features.sort 决定是否启用 sort 排序;若启用则 sort ASC、id DESC,否则仅按 id DESC。

案例内容的 CRUD 示例(基于模型)

  • 创建案例:
    • 使用后台 Cases 模型填充字段(title、content、image、keywords、description、sort、status、operator_type、operator_id、created_at 等)。
    • 参考:后台模型 Cases.php:68-81
  • 更新案例:
    • 通过主键定位记录,更新任意可写字段(如 title、content、image、status、sort)。
    • 参考:后台模型 Cases.php:68-81
  • 删除案例:
    • 删除记录后,相关附件与关联数据由模型 Concerns 处理清理。
    • 参考:后台模型 Cases.php:31-35
  • 查询案例:
    • 已发布列表:使用前台 Cases 模型的 published() 作用域。
    • 归档筛选:使用 archive 时间窗筛选。
    • 有图筛选:使用 imageNotEmpty() 作用域。
    • 参考:前台模型 Cases.php:117-136、前台模型 Cases.php:138-154、前台模型 Cases.php:156-165

查询优化策略

  • 使用作用域缩小结果集:
    • published():仅返回已发布案例。
    • filterByArchive():按年/月时间窗筛选,减少扫描范围。
    • imageNotEmpty():仅返回含主图的案例。
  • 利用默认排序:
    • 前台默认 sort ASC, id DESC,保证稳定且高效排序。
  • 批量预热:
    • 使用 prefetchers 批量预热 URL、多语言值与附件,避免 N+1 查询。
  • 关联加载:
    • with('category') 批量加载分类信息,减少多次查询。
  • 索引建议:
    • 确保 category_id、status、created_at 具备合适索引以提升筛选与排序性能。
    • 参考:升级脚本 cases/_update/data/upgrade.php:114-117

依赖关系分析

  • 表间关系:
    • cases.category_id → cases_category.id(一对多)。
  • 模型依赖:
    • Cases 模型通过 belongsTo 关联 CasesCategory。
    • 前台模型使用 Concerns 提供 URL、多语言、附件、列表字段等能力。
  • 升级脚本依赖:
    • 在重命名表之前完成字段补齐与数据迁移,确保向后兼容。
classDiagram
class Cases {
+int category_id
+string title
+text content
+string image
+string keywords
+string description
+tinyint status
+int sort
+int click
+datetime created_at
+enum operator_type
+int operator_id
+category()
}
class CasesCategory {
+smallint id
+string name
+string slug
+smallint parent_id
+string icon
+string keywords
+string description
+tinyint sync_to_nav
+int sort
}
Cases --> CasesCategory : "belongsTo(category_id)"

性能考虑

  • 列表页优先使用 published() 与归档筛选,减少不必要的数据扫描。
  • 使用 prefetchers 批量预热 URL、多语言与附件,避免 N+1 查询。
  • 合理设置索引:category_id、status、created_at、slug(如需按 slug 查询)。
  • 排序尽量使用 sort + id 组合,保证稳定性与效率。
  • 大字段(content)仅在详情页加载,列表页避免全量传输。

故障排查指南

  • 时间字段异常:
    • 确认 created_at 是否为空或由系统生成;避免手动修改。
    • 参考:升级脚本 cases/_update/data/upgrade.php:156-166
  • 分类层级错乱:
    • 检查 parent_id 是否正确指向父分类 id。
    • 参考:后台模型 CasesCategory.php:61-70
  • 图片不显示:
    • 确认 image 字段存储的是附件编号,而非原始路径。
    • 参考:前台模型 Cases.php:51-73
  • 未找到已发布案例:
    • 检查 status 是否为 1。
    • 参考:前台模型 Cases.php:127-136

结论

DouPHP 案例模块通过清晰的表结构与模型抽象,实现了案例内容与分类的高效管理。主表涵盖标题、内容、图片、SEO、状态、排序、统计与创建者信息;分类表支持层级与唯一标识。结合升级脚本的规范化与索引优化,以及前台模型的查询增强,整体具备良好的可扩展性与性能表现。开发者可依据本文档进行 CRUD 操作与查询优化,保障案例展示系统的稳定运行。

附录

  • 表结构参考:
    • 案例主表与分类表的完整建表语句请参考备份 SQL。
    • 参考:备份 SQL cases.sql
添加日期:2026-10-05